Sitemap
Press enter or click to view image in full size

From Spring to Jmix: A Real-World Implementation Case

5 min readFeb 6, 2026

--

We tested Jmix as an alternative to traditional Springand 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.

Press enter or click to view image in full size

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.

Press enter or click to view image in full size

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.

Press enter or click to view image in full size

🛸 Get an estimate of your digital idea 👉 hello@redcollar.co

💻 Website | LinkedIn | X | Instagram | Behance | Portfolio

--

--

Red Collar
Red Collar

Written by Red Collar

🏆 An award-winning agency with over a decade of expertise, delivering design and development services globally | 🌍 redcollar.co | 📩 hello@redcollar.co