From Spring to Jmix: A Real-World Implementation Case
We tested Jmix as an alternative to traditional Spring — and quickly built a news section for a GameDev project using it.
My name is Nikita, and I’m a Java developer at Red Collar. Today I’ll share why we chose Jmix, what specific features we encountered, and how we used the platform in a real project.
What is Jmix and Why It Might Be Right for You
Jmix is an open-source Java platform for rapid enterprise application development. It is the successor to the CUBA Platform and offers a wide range of built-in modules, including visual editors, code generators, migration tools, and more.
Since the platform is built on Spring Boot, it’s especially convenient for Java developers. You can use your familiar tech stack and integrate third-party libraries without learning new architectural principles. Jmix allows you to build both backend and UI within a single framework.
Making Development Easier: Jmix Studio
Jmix Studio is a plugin for IntelliJ IDEA that turns the platform into a full-fledged visual development environment:
- Quick project setup
- Data model generation
- Database migration configuration
- Visual screen and form building
You can combine manual coding with visual editing — speeding up routine tasks and minimizing errors. We were drawn to Jmix primarily for its speed and convenience.
The GameDev News Section on Jmix: Block-Based Structure
As part of the project, we had to build a news section with a block-based content system — allowing different types of blocks to be created, sorted, and configured on a single page. Jmix doesn’t provide this functionality out of the box, so we implemented it manually.
At the core is a Block interface with a type field. Each block inherits from it, defines its own type, and stores the necessary data.
public interface ContentBlock {
@JSONPropertyIgnore
BlockType getBlockType();
}public enum BlockType {
RICH_TEXT_AREA("richTextAreaBlock"),
PRIVACY_TERMS("privacyTermsBlock"),
CODE("codeBlock"),
QUOTE("quoteBlock"),
IMAGE_WITH_CAPTION("imageWithCaptionBlock"),
GAME_SCREENSHOT("gameScreenshot"),
GAME_FEATURE("gameFeature"),
ABOUT_VALUE("aboutValue"),
ABOUT_PERK("aboutPerk"),
GAME("game");
private String type;
BlockType(String type) {
this.type = type;
}
public String getType() {
return type;
}
}We created a separate visual component for each block to make data input easy. Inside each component, the block is treated as a separate state — allowing editing and saving. The visual components include buttons to change the order of blocks within the container.
public class RichTextAreaBlock implements Serializable, ContentBlock {
private final String type = getBlockType().getType();
private String label;
private String content;
@Override
@JSONPropertyIgnore
public BlockType getBlockType() {
return BlockType.RICH_TEXT_AREA;
}
}@UiController("RichTextAreaFragment")
@UiDescriptor("rich-text-area-fragment.xml")
public class RichTextAreaFragment extends ScreenFragment {
private RichTextAreaBlock state;
// ......
}To store the blocks, we used a JsonObject mapped to a Java class. Upon saving, we gather the states of all blocks, combine them into an array, and save the result in a table field.
As a result, we ended up with a flexible system that lets you assemble each material like a constructor.
Working with Text: Integrating a JavaScript Component
Once we implemented the block structure, we needed to edit text blocks — for news, job postings, etc. The default RichTextArea in Jmix wasn’t enough. We decided to integrate the external Quill editor via the JavaScript Component mechanism.
This involved:
- Declaring the component in the XML screen descriptor
- Connecting the necessary dependencies — local JS files and styles
- Creating a JavaScript connector
- Creating the component variable and callable methods in the Java class
JavaScript connector:
ui_ex1_components_javascript_RichTextEditor = function () {
let connector = this;
let element = connector.getElement();
element.innerHTML = `
<div id="${connector.getState().data.options.editorId}"/>
`;
connector.onStateChange = function () {
let state = connector.getState();
let data = state.data;
let toolbarOptions = {
container: [
[{header: [2, 3, 4, false]}],
["bold"],
["underline"],
[{list: "ordered"}, {list: "bullet"}],
[
{align: ""},
{align: "center"},
{align: "right"},
{align: "justify"},
],
["link"],
[{direction: "rtl"}],
["clean"],
],
};
let formats = ["link", "list", "header", "bold","underline", "direction", "align"];
let quill = new Quill(`#${connector.getState().data.options.editorId}`, {
theme: "snow",
formats: formats,
modules: {
toolbar: toolbarOptions,
},
});
quill.on('text-change', function (delta, oldDelta, source) {
if (source === 'user') {
connector.valueChanged(quill.getText(),
quill.getContents(),
quillGetHTML(quill.getContents()));
}
});
connector.setValue = function (value) {
quill.setContents(htmlToDelta(value))
quill.update();
}
}
function quillGetHTML(inputDelta) {
var tempCont = document.createElement("div");
(new Quill(tempCont)).setContents(inputDelta);
return tempCont.getElementsByClassName("ql-editor")[0].innerHTML;
}
function htmlToDelta(html) {
const div = document.createElement('div');
div.setAttribute('id', 'htmlToDelta');
div.innerHTML = `<div id="quillEditor" style="display:none">${html}</div>`;
document.body.appendChild(div);
let formats = ["link", "list", "header", "bold", "underline", "align", "direction"];
let toolbarOptions = [
[{header: [2, 3, 4, false]}],
["bold"],
[{list: "ordered"}, {list: "bullet"}],
[
{align: ""},
{align: "center"},
{align: "right"},
{align: "justify"},
],
[{direction: "rtl"}],
["link"],
["clean"], // remove formatting button
];
const quill = new Quill('#quillEditor', {
theme: 'snow',
formats: formats,
modules: {
toolbar: toolbarOptions,
},
});
const delta = quill.getContents();
document.getElementById('htmlToDelta').remove();
return delta;
}
};The result was a fully functional visual editor with a customizable toolbar. It’s easy to remove or rearrange buttons, keeping only the features you need.
Conclusion
Jmix is a great fit for tasks that require quickly building an admin panel, UI editor, or corporate web app from scratch. Java developers don’t need to become frontend engineers — just an understanding of architecture, some documentation, and the desire to automate repetitive tasks is enough.
If you’re already working with Spring Boot, learning Jmix will take minimal time — and the benefits will be noticeable in the very first sprints.
🛸 Get an estimate of your digital idea 👉 hello@redcollar.co
