Preface
In this quick start, we will scratch the surface of Jmix and develop a very simple but fully functional project management application. It will show the main things for creating any web application:
- How to design a data model.
- How to manipulate data.
- How to create business logic.
- How to add security.
- How to create a user interface.
This tutorial will be just enough for you to start your own Jmix application. In this tutorial, we will use Jmix Studio, so please install it before you begin and accept a trial subscription to access the visual designers.
Sample code repo: https://github.com/jmix-framework/jmix-quickstart.
Jmix project creation
We will create an empty Jmix project using the corresponding IntelliJ IDEA menu. We will use JDK 11.
With Jmix, you can generate project code based on templates. To create an application, let’s use the single-module-application
template.
Assign a name - jmix-pm
for your application.
After the project is created, you can move further with the help of the Jmix Tool Window that allows you to get access to different files and settings as well as add some project-specific objects.
Data model and database creation
The first task is creating entities. The business domain model has only two classes: Project
and Task
. The relation is one-to-many: one project can have many tasks.
For a start, let’s create the Project
entity. To do this, we can use a link to the project’s welcome page.
Another way is to right-click the Data Model node in the Jmix Tool Window and select New → JPA Entity.
Enter entity’s class - Project
. For this sample application, we do not need to change other entity parameters.
In the entity designer, create attributes according to the specification:
Name | Type | Mandatory |
name | String (255) | Yes |
startDate | LocalDate | |
endDate | LocalDate | |
manager | Association to the "User" entity, many-to-one cardinality | Yes |
In Jmix, we use standard JPA entities, so you can create them using either a code editor or a visual designer. Just click the + icon and add attributes to the entity. Jmix Studio will generate class members for you.
Look at how to add a mandatory reference to a user. The relation is many-to-one, so we’ll define an association field called manager
that references the User
class. Finally, the field definition should look like this:
In Jmix, you can specify a format for a proper entity display as a string in the UI using the Instance name field. For the Project
entity, we will select the name
attribute.
If we look at the Text tab at the bottom of the entity designer, we can see just a JPA-annotated Java class. The generated code can be updated if needed, and the designer will be updated accordingly when you switch to the Designer tab.
Let’s move further and create the Task
entity and link it to our Project
class. The fields specification table follows.
Name | Type | Mandatory |
name | String (255) | Yes |
assignee | Association to the "User" entity, many-to-one cardinality | Yes |
startDate | LocalDateTime | |
estimatedEfforts | Integer |
A task cannot exist without a project. This relation is called Composition
in Jmix. Let’s create a link between a task and a project. Open the Project
entity and create a composition attribute - tasks
- the list of tasks within Project
.
To make a link to Project
from the Task
entity, we need to create an inverse attribute in the task.
The data model is ready. Let’s generate database update scripts.
Expand the Data Stores node in the Jmix Tool Window, right-click Main Data Store and select Generate Liquibase Changelog.
Jmix Studio generates update scripts by comparing the existing database schema with the application data model.
For our project, we will use an in-memory database - HSQLDB.
Studio may ask us to apply existing scripts to align the application and the database state.
That’s it. The database has been created.
Generating CRUD admin screens
Jmix Studio contains a UI screen generation wizard that helps us to create basic but useful UI screens:
- Browser - to show the list of entities in a grid.
- Editor - to edit one entity instance using a form-like user interface.
First, we will create screens to work with projects. Start a wizard by clicking the Create screen menu item in the Screens menu on the top of the entity designer.
Also, you can use Jmix tool window to start the screen generation wizard. Open the context menu by clicking the + icon in the toolbar and select Screen.
Select Entity browser and editor screens in the wizard.
Then click Next and stop at the Entity browser fetch plan step.
In Jmix, we can define several fetch plans for every entity. They specify which fields will be fetched from the database. You can define fetch plans in a separate file to use them in different modules of your application or create an inline fetch plan while creating a screen.
Let’s create an inline fetch plan. In addition to the selected properties, mark the manager
reference.
At the next step, let’s add both manager
and tasks
fields.
Click Next at the next step and finish screens creation.
As you can see, each screen consists of two parts: a controller, written in Java, which is responsible for internal screen logic and events handling, and an XML layout that defines the screen appearance. In our case, the browser consists of the ProjectBrowse.java
and project-browse.xml
files and the editor - ProjectEdit.java
and project-edit.xml
accordingly.
You can find XML descriptors in the Data Model sections in the Jmix Tool Window.
To open the controller, use the context menu.
Please pay attention to the data section in the XML screen descriptors - it defines how the data is fetched from the database.
<data readOnly="true">
<collection id="projectsDc"
class="com.company.jmixpm.entity.Project">
<fetchPlan extends="_base">
<property name="manager" fetchPlan="_base"/>
</fetchPlan>
<loader id="projectsDl">
<query>
<![CDATA[select e from Project e]]>
</query>
</loader>
</collection>
</data>
After screens are created, you can preview a screen by using buttons in the top right corner of the screen layout editor. The preview shows that all selected attributes are added to the screens.
UI components can be bound to data in a bidirectional way. All changes in the bound fields are reflected in the selected data and vice versa.
Now let’s generate CRUD screens for the Task
entity. With the Task
, we will also fetch Assignee
and Project
entities.
At the next step, the necessary fields are already selected.
You can easily navigate between a screen controller, descriptor, and linked entities with Jmix Studio using buttons on the top of the window:
Running application in the development mode
To run the application, you can use the Run Configuration tool on the top of the IDE window.
After some time, you can access the application using the browser. By default, the URL will be
localhost:8080 .
You can see the application log file at the bottom of the IDE in the Run window.
Open the URL in your browser and log into the application using admin
as a username. The password is admin
by default.
You can find screens for entities manipulation under the Application menu.
Then let’s add some data to the database. Create a new project and assign the admin
user as a manager.
We can add a task when creating a project.
Let’s create a new user - dev1 - as an assignee for this task.
Save the newly created project. The task will be saved automatically.
Adding security
In Jmix, you can create roles and give them permissions to access the application data such as particular entities, attributes, or functionality like screens and menu items, in the admin UI.
Open the Resource roles screen and create the "Developer" role. Select Entity policy from the list and allow developers to view and edit tasks.
Then allow developers to edit task estimated time and start date only.
Finally, add permissions to view browser and editor screens. Select Grant access to the menu item to add Tasks to the main menu.
Then, switch to the Child roles tab and add another role to the "Developer" - the "UI: minimal access" role that allows users to log in to the application.
Let’s assign the role "Developer" to the "dev1" user. Select Role assignments for the necessary user in the Users screen.
Now let’s log in as Developer One. We can see that this user has access to the specified screens and attributes only.
Adding business logic
Now we will use Jmix Studio to create a service that implements business logic, and use this service in a screen. It will be a Spring service that will return the least busy user. In the admin UI, we will use this service to assign a task to this user by default.
Use a toolbar in the Jmix tool window to open commonly used actions. Select Spring Bean and enter the class name - TaskService
.
Studio will generate an empty Spring bean. Replace the @Component
annotation with @Service
.
Let’s create the findLeastBusyUser()
method. In the service, we will use the Jmix service - DataManager
. It allows us to access data by using a JPQL query.
Inject DataManager
into the service by using the Inject button on the top of the window.
Select DataManager
in the pop-up window.
Add the method’s implementation represented below:
@Service
public class TaskService {
@Autowired
private DataManager dataManager;
public User findLeastBusyUser() {
User leastBusyUser = dataManager.loadValues("select u, count(t.id) " + // (1)
"from User u left outer join Task_ t " +
"on u = t.assignee " +
"group by u order by count(t.id)")
.properties("user", "tasks")
.list().stream().map(e -> e.<User>getValue("user"))
.findFirst() // (2)
.orElseThrow(IllegalStateException::new);
return leastBusyUser; // (3)
}
}
- A JPQL query that selects users and counts tasks assigned to these users.
- Takes the first user in the selected set.
- Returns the user.
The service is ready, let’s use it in the task editor screen.
Click the Generate Handler button on the top of the window with the screen controller and select the InitEntity
event.
Here is the implementation of the method:
public class TaskEdit extends StandardEditor<Task> {
@Autowired
private TaskService taskService; // (1)
@Subscribe
public void onInitEntity(InitEntityEvent<Task> event) {
event.getEntity().setAssignee(taskService.findLeastBusyUser()); // (2)
}
}
- Inject the
TaskService
into the screen. - Assign the execution result to the
assignee
field of the created task.
That’s it. Let’s restart the application and see the service execution in action.
First, let’s add one more developer - dev2
.
We have one task assigned to Developer One, so an Admin or Developer Two will be the next least busy developer.
After adding four tasks, the next least busy developer will be either Admin or Developer One, they both have one task each.
Deploy
Let’s see how to deploy a Jmix application with an executable JAR file.
First, run the boot:jar
command in Jmix Studio.
The file is ready. Navigate to the folder with the file.
Then, execute the command java -jar <file_name>
.
Now you can open the browser and see the application running.
Conclusion
With Jmix, you can implement a ready-to-deploy Spring Boot application in minutes, thanks to the powerful development tools and code generators.