<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Jmix - Blogposts</title>
        <link>/rss.xml</link>
        <description>Jmix - Blogposts</description>
        <lastBuildDate>Thu, 12 Mar 2026 11:19:11 GMT</lastBuildDate>
        <docs>http://blogs.law.harvard.edu/tech/rss</docs>
        <generator>https://github.com/nuxt-community/feed-module</generator>
        <category>Jmix - Blogposts</category>
        <item>
            <title><![CDATA[Domain-Driven Design in Jamix: DDD Principles and Application Examples]]></title>
            <link>https://www.jmix.io/blog/implementing-domain-driven-design-in-enterprise-java-applications-with-jmix</link>
            <guid>https://www.jmix.io/blog/implementing-domain-driven-design-in-enterprise-java-applications-with-jmix</guid>
            <pubDate>Thu, 05 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/DDD_8ed5742495.png">Let's look at how Domain-Driven Design helps model complex business processes (using ERP systems for manufacturing as an example), and Jmix helps quickly implement these domain models in an enterprise application with a ready-made UI, database, and API.]]></description>
            <content:encoded><![CDATA[## What Is DDD, and Why Should You Care?

Building software is hard. Building software that scales well, stays maintainable, and performs under real-world pressure is even harder. The industry has produced dozens (if not hundreds) of approaches, patterns, and paradigms to tackle this challenge. This article offers a pragmatic take on one of them: Domain-Driven Design.

The textbook definition — from [Eric Evans' Domain-Driven Design](https://www.domaindrivendesign.org/) (2004) — goes something like this:

*Domain-Driven Design (DDD) is a set of principles and patterns aimed at creating optimal object systems. It centres on building software abstractions called domain models, which encode business logic that connects real-world conditions to code.*

That’s a mouthful. To put it simply: *DDD means building an application as if you were explaining it to the business, not to a programmer.*

The approach rests on several core principles. In this article, I’ll walk through the main ones and a few supplementary ones, illustrating each with examples drawn from an ERP system for a small manufacturing company. Along the way, we’ll see where Jmix can be useful.

## DDD Principles at a Glance

Here’s a quick overview of what we’ll cover:
- Ubiquitous Language — a shared vocabulary for everyone
- Bounded Contexts — autonomous modules with clear responsibilities
- Aggregates — encapsulated business rules
- Entities and Value Objects — modelling reality, not database tables
- Core Domain — isolating the domain model
- Domain Events — reacting to meaningful state changes

Here’s a closer look at each one.

### Ubiquitous Language (Core Principle)

Every participant in the development process — developers, analysts, testers, and the business itself — must use the same terms to describe the application’s processes, data, and rules. When the language drifts between conversations and code, understanding drifts with it.

#### *Anti-pattern — technical jargon obscures business meaning*

A production technologist says: “Cutting a sheet of plywood wastes about 20%. For a run of 100 units, we need to order extra material.” The developer creates tables named materials, waste_coefficient, production_requests. Where is “cutting layout” in that schema? What does waste_coefficient actually mean? The business meaning is lost. A new developer joining the team may never recover it.

Better approach — domain terms become classes and methods

```
class TechnologyMap {  

private Material material; 

 private Decimal wastePercent; // "waste"

private Integer resultQty; // "cutting yield"

public MaterialCalculation calculateMaterialFor(Batch batch) { 
	     // "calculate material requirement for a production run"
	} 

} 

class Batch {  

private int qty; // 100 units

 private Product product; 

 }
```  

Now, when the technologist and the developer look at the code together, they understand each other. Changing the waste rate means changing one place: the TechnologyMap class.

When these entities are Jmix entities (annotated with @JmixEntity), Jmix Studio automatically generates matching field names, column names, and view labels — not just for ordinary getters and setters, but also for additional, correctly annotated methods tied to business logic. This makes the ubiquitous language truly ubiquitous: in the code, in conversation, and in the user interface.

### Bounded Contexts (Core Principle)

A large system should be split into independent modules (contexts), each with its own responsibility and its own internal model. In a manufacturing ERP, the obvious candidates are warehousing, customer management and orders, procurement, production, and so on.

#### *Anti-pattern — everything in one heap*

A monolithic Product class holds everything: SKU, selling price, cost price, production process descriptions, stock levels, photographs, and a hundred other attributes. Procurement, production, and sales all depend on it. When accounting asks for a change in cost calculation — say, adding labour-time tracking — the ripple effects are unpredictable. The system becomes brittle.

#### *Better approach — divide and conquer*

- ProductProject context: the Product here is essentially a blueprint. Fields: drawing, TechnologyMap, MaterialCalculation. It knows nothing about stock levels, and it shouldn’t.
- Production context: ProductionTask is a work order for the shop floor. It references the product, the run size, and a status (in progress, completed, cancelled, etc.). It describes what needs to happen right now.
- Warehouse context: StockProduct represents a physical object on a shelf. Fields: Material, Product, qty, selfCost, WarehouseSlot. No knowledge of production technology or customers — just quantity and cost.
- Sales context: ProductPosition is a catalogue entry. Fields: photo, clientDescription, price, ProductLink. No knowledge of cost price — only the selling price.

With this separation, changing a painting technology in ProductProject doesn’t ripple into other contexts. Accounting can revise the cost-calculation algorithm in Warehouse without risking the customer-facing catalogue. The system becomes modular, resilient to change, and far easier to maintain.

Jmix makes it straightforward to build modular (composite) applications, which maps neatly onto bounded contexts. Jmix Studio provides everything you need for managing such projects, from templates to specialised views. There are also convenient tools for managing inter-module dependencies — see the documentation for details.

### Aggregates (Supplementary Principle)

An aggregate is a cluster of related objects governed by a single root object. All mutations flow through that root — there is no other way in. This guarantees that business rules and invariants (for example, “you cannot ship items to a customer that have not been manufactured”) are always enforced. Think of an aggregate as a black-box class with no public getters or setters, controllable only through business methods.

#### *Anti-pattern - anyone can change anything*

- A manager edits the price on an already-approved order:
```
OrderLineItem item = orderLineRepository.findById(lineId); 
item.setPrice(new BigDecimal("500")); // Was 700 
item.save(); // Financial error: agreed on one price, invoiced another.
```

- A discount system sets a 50% discount directly:
```
order.setTotalDiscount(new BigDecimal("0.5")); 
// 50% discount, but the manager's limit is 15%.
```

#### *Better approach - one entry point, enforced rules*

```
class Order {  

private OrderId id;     
private OrderStatus status;     
private Client client;     
private List<OrderItem> orderItems; // Internal, not exposed     
private Discount discount;     
private LocalDateTime fixedPriceDate;

 // No public getters or setters for fields
 
 // === INVARIANTS ===     
// 1. Prices are locked at the moment of approval     
// 2. Line items may only be modified while status is DRAFT     
// 3. Discount must not exceed the manager's limit     
// 4. Status transitions are strictly controlled
 
// === Public methods: the only way to mutate the aggregate ===
 

public void addPosition(Product product, Qty qty) { 
    if (this.status != OrderStatus.DRAFT) { 
        throw new DomainException("Items can only be changed while the order is a draft."); 
    } 
    Price fixedPrice = priceService.getCurrentPrice(product); 
    this.orderItems.add(new OrderItem(product, qty, fixedPrice)); 
    this.recalculateOrder(); 
} 
 
public void applyDiscount(Discount discount, User manager) { 
    if (discount.greaterThan(manager.getDiscountLimit())) { 
        throw new DomainException("Discount exceeds the manager's authority limit."); 
    } 
    this.discount = new Discount(discount); 
    this.recalculateOrder(); 
} 
 
// Other methods omitted
} 
```

The code above is illustrative, not a production template.

Some context is worth noting here. DDD and JPA are, frankly, an awkward fit:
- DDD demands full encapsulation — all changes must go through the aggregate root.
- JPA in general, and Jmix in particular, rely on data-access interfaces, entity relationships, and similar mechanisms. These often grant access to entities from practically anywhere (views, service beans, repositories), which conflicts with the aggregate pattern.
- Jmix also generates editing views for entities, which doesn’t help encapsulation either.

This might look like Jmix and DDD are at odds, but that’s not the full picture. Like most methodologies, DDD is a set of guiding principles, not dogma — and aggregates are not even one of its foundational tenets.

Encapsulation and invariant enforcement can still be achieved alongside Jmix’s tooling. For example:
- Guard invariants at multiple levels: private methods inside the entity, business-method validation in Spring service beans, and persistence-level constraints.
- Separate the model into read and write layers. This is harder, but remains a viable option.
- Use Jmix entity events for event-driven validation and auditing to prevent unwanted changes.
- Delegate mutating operations from standard views to services with strict validation logic — essentially overriding default behaviour and applying validation by contract.

In short, the aggregate pattern is achievable in Jmix, though not to purist standards. Studio’s tooling makes implementing invariant guards less labour-intensive. Pay special attention to Jmix’s composition mechanism and the @Composition annotation. When a relationship is marked as a composition, child entities are saved only when the parent is saved — a natural fit for aggregate semantics. Details are in the documentation.

### Entities and Value Objects (Core Principle)

The core idea here is that we model real-world objects and processes, not database table structures. Database design has its own specialists. In DDD, we work with two fundamental building blocks — Entities and Value Objects — and they are not the same thing.

An Entity has identity and a lifecycle. Each instance is unique and tracked throughout its existence. Its identifier matters more than its contents.

#### Examples:
- Order with ID 547 — customer order number 547. Even if its contents or delivery address change, it remains the same order.
- MaterialBatch with ID “FAN-034” dated 30 October 2025 — a batch of plywood with a specific cost.

A Value Object is defined entirely by its attributes. It has no identity. If all fields match, two instances are interchangeable and may be freely copied.

#### Examples:
- DeliveryAddress (15 High Street, Flat 34) — if two orders share the same address, it is the same address.
- MoneyAmount — twenty pounds is always twenty pounds.

The takeaway is straightforward: model production entities such as Task, Order, and Batch with unique identity, and model characteristics such as Sizes, Weight, Price, and Address as immutable value objects. The result is a system that behaves predictably — like a real production line, not a collection of database tables.

Jmix’s data layer is built on JPA, so all entities are ORM entities. But for DDD, the distinction matters:
- A DDD Entity is roughly analogous to a noun — it doesn’t imply a specific implementation. In Jmix, this maps well to a JPA entity with an emphasis on identity and behaviour. @JmixEntity is a natural fit.

A DDD Value Object can be implemented as:
- An @Embeddable class (stored in the parent’s table).
- A non-JPA class used only in business logic — a DTO or plain POJO.
- Custom data types with straightforward UI support, which are in effect value-object implementations.

One common DDD technique is to create a separate entity or class with equals()/hashCode() based on field values. In Jmix, this should be avoided, because Jmix’s build-time entity enhancement mechanism relies on its own identity handling.

### Core Domain — Isolating the Domain Layer (Supplementary principle)

In DDD, the domain layer is sacred. It contains pure business logic and must not depend on databases, external services, frameworks, or UI implementations. Those “technical” concerns belong in separate layers (Infrastructure, Application). We’ll skip worked examples here and focus on the theoretical benefits:
- Testability — domain logic can be tested without a database or a web server.
- Replaceability — you can swap PostgreSQL for another database without touching business logic.
- Focus — a developer working on the domain layer thinks about the business, not about plumbing.

Jmix inherently separates an application into layers:
- UI layer — view controllers, view descriptors, menus, and message bundles.
- Service layer — your Spring beans.
- Entity layer — the entity model. Note that this is not a pure domain model in the DDD sense, which is an important distinction.
- Data Access layer — if you need or prefer one, you can create a dedicated repository layer.

Now for the pragmatic bit: dogma versus trade-offs. A pure domain model in Java means plain Java code — no third-party annotations, no JPA, and certainly no Jmix. That sounds elegant, and all the benefits listed above apply. But making POJO classes do real work means dealing with a few practicalities:
- Data persistence — you probably want a database, not just in-memory storage. That requires additional layers, from raw JDBC up to JPA.
- Data processing — a domain model exists to serve business tasks, not to look good on paper. Data needs to be mutated, validated, passed between modules, and sent to external services. At the domain-model level this looks simple; the implementation may take longer than expected.

A pure domain model is an appealing ideal, but it is just that — an ideal. Jmix offers a pragmatic, modified DDD approach built around a Unified Data Model, which saves significant development time by compressing the data-layer stack. You don’t need domain-to-persistence mappers, JPA wrappers, or custom REST controllers. If you can set aside purist concerns, this approach delivers strong results for enterprise applications with conventional web UIs.

### Domain Events via the Event Model (Supplementary principle)

DDD recommends using domain events. Jmix ships with a robust event system covering both standard JPA entity-lifecycle events and Jmix-specific events. Event listeners let you detect and react to entity changes before or after a transaction commits, and they carry information about the type of change and other useful context. For full details, see the entity events documentation.

## Using Jmix in a DDD-Aligned Workflow

### Rapid Prototyping with a Reasonably Clean Domain

With classical DDD, a lot of time goes into standing up infrastructure — database connectivity, a minimal UI, and so on — before you see a working application.

With Jmix, you define domain entities (following DDD principles), and Jmix automatically generates:
- Database tables
- CRUD views
- A REST API (if needed)

For example, suppose you model ProductionTask as an aggregate. Within minutes you get:
- A creation view (Jmix StandardDetailView)
- A list view (Jmix StandardListView) with filtering, pagination, and grouping
- An editing form within the same detail view
- REST endpoints after adding the REST API add-on, which takes about fifteen seconds to install and gives you endpoints straight away

Later, you can replace the generated views with custom ones, or drop them entirely and build a front end in modern JavaScript — the domain model stays intact. And “a few minutes” is not a figure of speech. Jmix Studio’s tooling enables remarkable speed:
- View wizards for scaffolding list and detail views from the model in a few clicks
- An entity designer for quickly adding validation, localisation, and more
- A role designer for visual access-control management with role-hierarchy support

Beyond Studio itself, Jmix provides a large library of ready-to-use add-ons — from report generation to business-process automation. Here are a few highlights.

### Visual Designer for Complex Business Processes

For complex systems such as the ERP described above, business processes are essential. Jmix covers this ground well.

The Jmix BPM add-on lets you:
- Visually design processes (much like a BPMS) directly within the running application — and use Jmix views as process forms.
- Integrate those processes with your domain model.
- Launch and monitor execution with a convenient UI for both processes and user tasks.

### Ready-Made Components for Common Business Tasks

- Printed forms (orders, invoices, reports, etc.) — the Reports add-on
- Audit trail (who changed what, and when, in any aggregate or entity) — the Audit add-on
- REST DataStore — another take on module and context separation; popular with the community

### Integration with External Systems

Manufacturing rarely operates in isolation. Common requirements include exporting orders to an accounting system, pushing data to finance platforms, and integrating with marketplaces.

Jmix offers:
- A built-in REST API (mentioned above)
- Integration with Kafka and RabbitMQ for asynchronous communication between contexts — the full power of Spring Boot is at your disposal
- Scheduled tasks via the Quartz add-on

## Conclusion

Domain-Driven Design is a compelling pattern for building large, complex enterprise applications. Jmix is a platform built for exactly that class of systems. Combining DDD thinking with Jmix’s capabilities lets you build things right and build them fast, affordably, on a transparent and modern technology stack.

Most importantly, a project started on Jmix benefits from a battle-tested architecture that can evolve as functionality grows, without costly redesigns.

To sum up:
- DDD and Jmix are not opposites — they are a sensible combination.
- Use DDD principles to develop a deep understanding of the business and to build the right architecture.
- Use Jmix to deliver predictable results quickly, avoid writing the same code twice, and stay out of infrastructure rabbit holes.
- Balance is the key: take from DDD the principles that yield the greatest benefit for the least overhead (Ubiquitous Language, Bounded Contexts, Value Objects), and take from Jmix the development speed, Studio tooling, and the ecosystem of ready-made components and add-ons.

Jmix itself is a free, open-source framework. Applications you build with it are entirely yours. Most add-ons can be used without a Jmix Studio subscription.

You can try the full Jmix Studio experience free for 28 days here. Students get free access for the duration of their studies, upon request. Studio is also free for small projects.


]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar «Building a Lab System: From Experimental Data to a Maintainable Platform»]]></title>
            <link>https://www.jmix.io/blog/webinar-building-a-lab-system-from-experimental-data-to-a-maintainable-platform</link>
            <guid>https://www.jmix.io/blog/webinar-building-a-lab-system-from-experimental-data-to-a-maintainable-platform</guid>
            <pubDate>Fri, 27 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Webinar_Building_a_Lab_System_1200x630_Blog_78c6bbe014.png">It’s been a while since we last met with our academic community, so we’re especially happy to have a great reason to reconnect. This time, it’s a story we truly wanted to share.]]></description>
            <content:encoded><![CDATA[It’s been a while since we last met with our academic community, so we’re especially happy to have a great reason to reconnect. This time, it’s a story we truly wanted to share.

On February 25 we hosted a webinar **«Building a Lab System: From Experimental Data to a Maintainable Platform»**. It was inspiring and useful.

It was about how real research software is born - not as a student prototype, but as a system that laboratories rely on every day.

Research lab software rarely starts as “real” software. It grows around experiments, spreadsheets and scripts, built by students or researchers to solve immediate tasks. Over time, these tools turn into mission-critical systems, but maintaining and evolving them becomes increasingly difficult.

Our Academic Program Lead [Viktoriia Klementeva](https://www.linkedin.com/in/viktoriia-klementeva-601708295/) hosted a live interview with our special guest - [Pasquale Granato](https://www.linkedin.com/in/pasqualegranato/), Researcher at the ISAAC Institute, SUPSI (University of Applied Sciences and Arts of Southern Switzerland).

He shared how his photovoltaic lab built a single, maintainable system with Jmix - covering experimental data management, test planning and long-term time-series storage.

We had a conversation not only about technology, but about the journey: from scattered scripts and spreadsheets to a unified research platform.

This webinar especially useful for:
- Professors & PIs running research labs.
- Research staff and lab managers.
- Students maintaining lab infrastructure.
- R&D teams with too much code and not enough developers.

**Watch the record of the webinar below** 

<iframe width="560" height="315" class="b-youtube-player" src="https://www.youtube.com/embed/9Nr2VjAmCC8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix and the Rise of Coding Agents]]></title>
            <link>https://www.jmix.io/blog/jmix-and-the-rise-of-coding-agents</link>
            <guid>https://www.jmix.io/blog/jmix-and-the-rise-of-coding-agents</guid>
            <pubDate>Thu, 12 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Vibecoding_ENG_939533e13b.png">How AI coding agents accelerate and simplify enterprise Java development on Jmix - with practical examples, common pitfalls and a step-by-step guide from our developer.]]></description>
            <content:encoded><![CDATA[I'm a Jmix developer. Enterprise Java, Vaadin screens, security roles - the usual stuff.  

At some point I caught myself wondering: everyone's out there vibe-coding React apps and Python scripts in minutes. But what about Jmix?  Is it something LLMs can handle — and if so, how well? 
 
I wanted to quit after the first week. Out of 120 generated classes, only a couple dozen made it to production. LLMs confidently invented APIs that didn't exist, mixed up Jmix versions,  and insisted on using EntityManager where it  didn’t belong. Infuriating.  Things got better by the second week: I was only throwing out every fifth file instead of everything. By week three, I barely had to redo anything. 

What made the difference? Configuration. I'll show you how to set it up.

## Key Problem: "Done" by LLM Doesn't Mean "Working" 

LLMs love to declare victory as soon as code compiles. Like "Done!", time to celebrate =) Sometimes, if their conscience bothers them (which rarely happens for now and mainly with the most expensive models), they might think to run tests. And you get a response like "done, waiting for review, everything works / everything fixed". Yeah, right. 

In my first month of experiments, the errors roughly fell into three groups. About a quarter were compile-time issues — missing imports, type typos — small things LLMs handle easily. Another quarter were startup failures, where the application wouldn’t start: Spring failed to initialise, Liquibase broke on migrations. These are usually straightforward to fix by having the agent run the app and inspect the logs. 

The remaining issues showed up at runtime: opening a screen and hitting a NullPointerException, clicking a button and nothing happening, saving an entity and ending up with broken data. These take more effort and attention.Typical scenario: LLM wrote a view (e.g. screen / page), code compiled, application started. "Done!!". You open the screen and hit an Exception. Or the button doesn't work. Or data doesn't save. Then the exhausting cycle kicks in: test, explain, LLM fixes, and test again. TIME AND TIME AGAIN. 

All that speed disappears into this cycle. Fortunately, I found an efficient way to break this exhausting circle. 

## Best models to work with Jmix 

There are many different kinds of LLMs now, and their quality can vary significantly depending on the task. Jmix is no exception, so I put together my own rating as it stands at the beginning of 2026. 

**Top tier (Claude Opus, Gemini Pro, Codex 5.2).** Work almost without context. Know Jmix 2.x, understand Vaadin Flow, and rarely hallucinate. You can work with them productively. 

**Mid-tier (Claude Sonnet, GPT-4/5, Gemini Flash).** Know the basics but make things up. Might use @GeneratedValue instead of @JmixGeneratedValue, or forget @InstanceName. With good context, they work reasonably well. 

**Cheap and local (Codestral, Qwen, Llama 3).** Hallucinate constantly. The code looks convincing — production-ready until you actually run it. 

Here is an example for prompt: "create entity Customer with fields name, email": 
- **Opus:** @JmixEntity + @Entity + UUID + @Version + @InstanceName → works 
- **GPT:** @Entity + @GeneratedValue (without @JmixEntity) → compiles, doesn't work 

Why doesn't the GPT version work? Jmix doesn't see the entity without @JmixEntity: it won't appear in UI, DataManager won't find it, Studio won't generate screens. Code compiles, app starts, but the entity is like it doesn't exist. Classic runtime error that you catch after an hour of debugging. 

Context files help everyone: top models avoid such errors, and weaker ones at least work somehow. 

## Platforms: Where to Run the Model 

Right now, all platforms support different vendors - you can use Opus in Cursor or Amazon Bedrock in Claude Code. So, choose by convenience, not by model. 

<style>
.table_1 {
    overflow: auto;
    width: 100%;
    margin: 0 0 20px;
}

.table_1 table {
    border: 1px solid #342a98;
    table-layout: fixed;
    border-collapse: collapse;
    border-spacing: 1px;
    text-align: left;
}

.table_1 caption {
    caption-side: top;
    text-align: left;
}

.table_1 th {
    border: 1px solid #342a98;
    background-color: #e8e2ff;
    padding: 5px;
}

.table_1 td {
    border: 1px solid #342a98;
    background-color: #ffffff;
    padding: 5px;
}
</style>
<div class="table_1" role="region" tabindex="0">
<table>
    <caption><br></caption>
    <thead>
        <tr>
            <th>Platform</th>
            <th>For whom</th>
            <th>Pros</th>
            <th>Cons</th>
            <th>Pricing model</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><b>Cursor</b></td>
            <td>VS Code users</td>
            <td>Sub-agents, multi-model evaluation, automatic context</td>
            <td>No integration with Jmix Studio</td>
            <td>Ultimate ≈ $200/month. Includes a total of ~$400 you can burn across different AI provider APIs</td>
        </tr>
        <tr>
            <td><b>Claude Code</b></td>
            <td>Any editor</td>
            <td>Terminal-based agent, 5–10 parallel agents</td>
            <td>Loses context in long sessions</td>
            <td>Max x20 subscription ≈ $200/month, essentially unlimited vibe-coding</td>
        </tr>
        <tr>
            <td><b>Junie</b></td>
            <td>IntelliJ IDEA users</td>
            <td>Native integration, sees full project structure</td>
            <td>Less proactive than Cursor</td>
            <td>Similar to Cursor (or more expensive), but for IDEA-based editors</td>
        </tr>
        <tr>
            <td><b>Continue</b></td>
            <td>Any editor&nbsp;</td>
            <td>Data stays local, highly configurable</td>
            <td>IMO tool calling is not well optimised</td>
            <td>Subscription-based or free (with third-party providers)</td>
        </tr>
    </tbody>
</table>
</div>

I tried them all. Settled on Claude Code with Max subscription: you can vibe-code without worrying about limits, run parallel agents (multiple real sessions, not sub-agents), don't count tokens at all. For NDA projects I use Continue with local models, but there you have to monitor more closely. 

Alright, let's say the platform is chosen and the model is connected. But remember that annoying cycle: opened screen, saw error, explained to agent, got fix, checked, error again? Platform alone doesn't break that cycle. You need one more piece of the puzzle. 

## MCP: Hands for the Agent 

MCP (Model Context Protocol) is like giving AI hands. Without it, LLM only generates text and hopes you'll check yourself. With MCP, the agent can dig into the IDE to look at errors, open a browser, and click buttons. 

I used two MCP servers for Jmix. 

**IDEA MCP** is the agent's eyes in the IDE. It sees not just compilation but Jmix Studio warnings: untranslated messages, broken XML references, fetch plan issues. Compiler lets those slide, Jmix Studio catches them. Saved me tons of debugging time, though you often have to push the LLM to actually use IDEA for static analysis. The agent often won't notice that, for example, our new enum isn't localized or that using certain beans is excessive when there's a simpler way. But Jmix Studio can tell all of this. 

**Playwright MCP** gives the agent a browser. It opens localhost:8080, logs in as admin/admin, and clicks through screens. Sees that a button doesn't work or form doesn't save data - and goes to fix it himself. 

Check this out: 

**WITHOUT MCP:** 
- Agent wrote view 
- Compiled -"done!" 
- You open it - error 
- You explain what's wrong 
- Agent fixes 
- Repeat steps 3-5 

**WITH MCP:** 
- Agent wrote view 
- Checked IDEA MCP - found warnings - fixed 
- Opened Playwright - clicked around - found bug - fixed 
- Gives you working code 

When the agent with Playwright first found a bug in a form on its own - without my hint, just clicked around and found it - my jaw literally dropped. This is it. This is how it should work. Since then, the agent has been finding most runtime bugs, not me. 

## Disclaimer  

Everything here is written for Claude Code. It is what I use and, in my opinion, it's currently the most capable agentic platform for Jmix development.  
 
That said, other platforms can do the same things, you'll just need to adapt. CLAUDE.md becomes AGENTS.md in Codex, MCP server setup looks a bit different in Cursor, et cetera. <u>The concepts are the same, the config files aren't.</u>

## Step-by-step instruction how to make it work 

To be more specific, I have shared the exact instructions on how to make this approach work below. 

### Install MCP Servers 

Setting this up took me three tries. The first time I fat-fingered the JSON and spent 20 minutes debugging syntax errors. The second time I mixed up the npx flags. But the third time, when I saw the agent open a browser on its own and start clicking buttons? That made it all worth it. 

We are going to install 3 MCP Servers: 
- **jetbrains** - connection with IntelliJ IDEA: compilation errors, Studio warnings, code navigation 
- **playwright** - browser: open page, click, screenshot, check UI 
- **context7** (optional) - needed if model doesn't know Jmix well (Sonnet, local models), will “google jmix things” through it 

You can configure it in ~/.claude/settings.json - all servers at once: 

```
{ 
  "mcpServers": { 
    "jetbrains": { 
      "command": "npx", 
      "args": [ 
        "-y", 
        "@jetbrains/mcp-proxy" 
      ] 
    }, 
    "playwright": { 
      "command": "npx", 
      "args": [ 
        "-y", 
        "@playwright/mcp" 
      ] 
    }, 
    "context7": { 
      "command": "npx", 
      "args": [ 
        "-y", 
        "@upstash/context7-mcp" 
      ] 
    } 
  } 
}
```
For IDEA 2025.2+ can use built-in SSE server (without npx): 

```
{ 
  "mcpServers": { 
    "jetbrains": { 
      "type": "sse", 
      "url": "http://localhost:65520/sse" 
    } 
  } 
}
```
Alternatively - via CLI (requires Node.js 18+): 

```
node - version  # check you have it 
 
claude mcp add jetbrains -- npx - y @jetbrains/mcp-proxy 
claude mcp add playwright -- npx - y @playwright/mcp 
 
# optionally, if model is small and doesn't know Jmix: 
claude mcp add context7 -- npx - y @upstash/context7-mcp
```

**Configure IDEA MCP**

Once MCP servers are setup some additional configuration within IntelliJ IDEA will be required. 

- File → Settings → Tools → MCP Servers 
- Add configuration (IDE usually offers a built-in server) 
- Or install the "MCP Server" plugin from Marketplace 

![]({{strapiUrl}}/uploads/kartinka_blog_zhmiks_f96b37bda3.jpg)

Once all MCP servers are configured, our agent can self-check himself by using IDEA's inspections and use proper project tools (way better than raw bash). And with Playwright MCP, the agent gets browser_navigate, browser_click, browser_screenshot — meaning the LLM can test the UI on its own. 

One caveat though: Playwright is slow. 10–20 seconds for a simple click, up to a minute for a form. When I need to iterate fast, I check manually. Playwright runs before commit as a final sanity check. 

## Setup: Minimum That Works

Create instructions for code Agents 

Don't copy the structure from cursor-boilerplate template project that you found in github: you do not need all 15 folders like /agents, /prompts, /skills and other. Don’t try to run for all this strange files like skills, agents, rules and other context neuro-slop files. You actually use maybe 10% of that. Especially, if you just start your “vibe-code carrier”.

**AI-README** 

One context file is enough. Name depends by platform – it can be CLAUDE.md or AGENTS.md or any other .md file. For details, check how does the context file named in your platform. 

**Minimal CLAUDE.md:**

```
# Project: Jmix 2.x Application 
 
## Role (optional) 
You  can describe what your agent is and what does he should be 
 
## Stack 
- Java 17, Spring Boot, Vaadin Flow 
- Database: HSQLDB (dev), PostgreSQL (prod) 
- Run: `./gradlew bootRun` (localhost:8080, admin/admin) 
 
## Rules 
- Entity: @JmixEntity + UUID (@JmixGeneratedValue) + @Version + @InstanceName 
- Data access: DataManager only (NOT EntityManager) 
- DI: constructor injection (no field @Autowired) 
- Views: XML descriptor + Java controller pair 
- All UI text: msg:// keys, add to ALL locale files 
 
## Forbidden 
- Lombok on entities 
- Business logic in views 
- Edits in frontend/generated/ 
```
The model knows what this project is, which rules apply, and what is forbidden. That's enough to start. After a few iterations, you'll naturally extend your “AI-README".md with fixes for common AI mistakes. Don't worry - at the end of the article, I'll share GitHub links with all the CLAUDE.md and RULES.md files that cover 90% of Jmix projects. 

**Prompt engineering**

No need to write 	a novel, here is a working structure: 

```
Study the project: look at CLAUDE.md, structure, existing entities and views. 
 
Create entity Order with fields: 
- customer (link to Customer) 
- date (order date) 
- total (amount) 
- status (enum: NEW, PROCESSING, DONE) 
 
Create list view and detail view for Order. 
Add to menu after Customers. 
Write unit test for OrderService. 
 
After each change, check via IDEA MCP (get_file_problems). 
When view is ready, open in browser via Playwright and check: 
- List displays 
- Creation works 
- Editing saves data 
 
Commit working piece with clear message. 
```
"Write unit test" isn't random here. **In fact, TDD with AI is a killer combo.** I used to be lazy about writing tests because it took time. Now AI writes them for me, and I ask it to cover everything. Extensive coverage is no longer a luxury; it is the norm. 

Why this matters specifically with vibe-coding: the agent in the next iteration might break what was working. Without tests, you may not notice it until changes arrive at production. With tests - agent sees red build itself and fixes it. Now I first ask to write tests for existing code, only then give a task for changes. 

## Brief recap

**Opus 4.5 + Claude Code + Playwright** is the "bare minimum" needed for vibe-coding with Jmix. Seriously, nothing else needed to start, everything else is just workflow optimizations and spending less on AI credits. Minimal setup (CLAUDE.md + clone repo) - about 15 minutes. With MCP - around an hour if you haven't configured before. By the end of the day I usually have 5-7 entities, dozen screens, and couple roles. Not a "full-featured CRM" but a foundation you can show and develop. 

**What's Mandatory** 
Here are requirements for common Jmix AI-agentic development in my opinion: 
- **Claude Opus 4.5** - top model, knows Jmix, rarely hallucinates. Can use Sonnet but with good context 
- **Claude Code** - terminal agent, reads/writes files itself, runs commands. Mandatory 
- **Playwright MCP** - agent opens browser and tests UI itself. Catches over half the bugs 
- **JetBrains MCP** - Studio warnings, compilation errors. Recommended, saves debugging time 
- **AI-README (CLAUDE.md / AGENTS.md)** - Dos and don'ts for the agent. Optional unless the LLM keeps making the same mistakes. Opus + React? Not needed. Sonnet + Jmix? Definitely needed. 

**What's Optional**
- **rules/, skills/** - folders with detailed instructions. Useful when project is large, but excessive for starting 
- **Multiple AI-READMEs** (.cursorrules, AGENTS.md) - only needed if using different platforms 
- **RAG/vector databases** - for huge codebases, not for starting 
- **Custom MCPs** - GitHub, Sentry, databases - add when needed 
- **Context7** (@upstash/context7-mcp) - MCP server for searching library documentation. We contributed Jmix support to it. The dumber the model - the more it needs to Google the docs, and Context7 saves here. Excessive for Opus, must-have for local models. Eventually embedding-based search will work even more precisely, but for now Context7 is a working option 

**Where to Get Files** 

Everything mentioned in the article is in [jmix-agent-guidelines](https://github.com/jmix-framework/jmix-agent-guidelines): 
- **AGENTS.md** - an open standard for guiding AI coding agents, used by 60k+ projects. A README for AI: build commands, code style, testing. Everything that any agent needs to work with your codebase. Works with Cursor, Copilot, Codex by default. 
- **ai-docs/rules/** - detailed rules by topics (entity, views, security) 
- **ai-docs/skills/** - step-by-step instructions for typical tasks 

Copy needed files to your project, adjust for yourself - and go. 

## Conclusions 

AI generates code faster than you. Jmix doesn't let it screw up too much - structure is strict. MCP lets the agent catch its own bugs. When all this works together - it's genuinely great. 

Forget "act as senior developer" and other incantations from 2023. With modern models, this is almost unnecessary - often they rewrite the prompt internally themselves (ReAct, Thinking mode). You write what you want to get, the agent does it. 

The only place that prompts still matter is when assigning roles to agents. "You're a reviewer, check code for security" or " you're a tester, find edge cases." Here the role formulation affects the result. Otherwise - just say what needs to be done. 

When you master the basic setup, you can speed up even more. With good architecture (modules, clear boundaries), run multiple agents in parallel - each works on its own folder. One builds one module, another another module, third writes tests for common API, etc. They don't interfere with each other if boundaries are clear. 

Even better through Cursor with sub-agents: The main model becomes an orchestrator, distributes tasks, and collects results. You get a whole team of neural nets with their own roles and workflows. One agent is an architect, another is a coder, and the third is a reviewer. Sounds like sci-fi but actually works. 

But this is optimization, not the starting point. First, learn with one agent, then scale. 

The approach described above works great for the CRUD, admin panels, prototypes, internal tools, but there are also some limitations where the results can be less positive: 
- Complex **business logic** AI handles it poorly. CRUD, typical operations, yes, easy. But I killed a whole day trying to get Claude to handle discount calculations with an accumulation system. Explained, showed examples, cursed. Claude kept confusing the calculation base and summing the wrong time periods. After 7 iterations I gave up and wrote it myself in two hours. State machines, tricky algorithms - same thing, better by hand (it can handle those too, **but it's way less fun**). 
- **Integrations** are a separate story. AI doesn't know your specific API, you'll have to explain every endpoint and check every call. Integration with a blood enterprise CRM systems SOAP service? I didn't even try handing that to the agent. 
- **Legacy without tests** – don't touch. Seriously. AI will climb in there and create such chaos you'll be cleaning up for a week. It doesn't understand that this hack from 2015 supports half the business logic. **Tests first, then vibe-coding.** 

Also about teams: AI amplifies the bad things too. If a person doesn't understand the code they're copying - bugs will end up in production. Code review for AI code is mandatory, especially with juniors. 

The final concideration is confidentiality: code goes to the cloud. If you're dealing with NDAs or personal data, use either local models or scrub the context clean. 
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Monitoring Active Users in Enterprise Applications with Jmix]]></title>
            <link>https://www.jmix.io/blog/monitoring-active-users-in-enterprise-applications-with-jmix</link>
            <guid>https://www.jmix.io/blog/monitoring-active-users-in-enterprise-applications-with-jmix</guid>
            <pubDate>Thu, 22 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/581853_66c378d509.png"> In today’s world, a wide range of metrics is used to assess the performance of different projects. Among them is the well-known set of engagement metrics: DAU, WAU, and MAU. What do these metrics actually mean, and why are they important?]]></description>
            <content:encoded><![CDATA[Once an enterprise application is released into production, it begins a life of its own. Quite often, implemented functionality is used differently from how it was originally designed—or not used at all. Business users tend to view the system from a different perspective, discovering their own paths and workarounds that can sometimes surprise the development team. 

Beyond questions of how features are used, an even more fundamental concern often arises: are users using the system at all? And if they are, what does “active usage” look like at an enterprise scale? 

<div class="purple-box">
  For example, you may want to understand how actively users are collaborating while working on a project, or how consistently the sales department is entering data that will later be used for analysis.
</div>
<style>
  .purple-box {
    background: #F5F5FD;
    border: 1px solid #342A98;
    border-radius: 16px;
    padding: 15px;
    margin: 20px 0;
  }
</style>

Depending on the business case, insights like these can support strategic decisions about further investment in the system. In this article, however, we will focus on the technical side of the problem and explore active user monitoring and how it can be implemented with Jmix. 

## Metrics for Active Users 

The metrics commonly used in enterprise applications to monitor user activity are largely the same as those used in the retail domain: 

**DAU (Daily Active Users)**– the number of unique users who engage with the system within a 24-hour window. This window works well in enterprise environments too, especially for multinational organisations with distributed teams and flexible working hours. 

**WAU (Weekly Active Users)**– the number of unique users who engage with the system during a week. 

**MAU (Monthly Active Users)** – the number of unique users who engage with the system during a month. 

It is important to note that WAU is not the sum of DAU values over a week, as each user is counted only once within the given period. The same applies to MAU: it is not equal to the sum of DAU or WAU values within a month. 

In addition to these metrics, there is a derived indicator known as **stickiness.** It is calculated as the ratio of the average number of daily active users to the number of weekly or monthly active users. 

![]({{strapiUrl}}/uploads/mau1_436e8c39e1.png)

Stickiness indicates how frequently end users engage with the system. A stickiness value of 100% means that the same users are active every day, which is typically a very positive sign. At the same time, weekly or monthly stickiness can decrease even if the average number of daily active users remains stable, revealing that different users are accessing the system on different days. 

<div class="purple-box">
For example, if developers are expected to fill in timesheets on a daily basis, stickiness metrics can clearly show how consistently this requirement is being followed. 
</div>

The calculations above can be adjusted to better reflect specific business scenarios: 
- **Experiment with averaging methods.** Try both the arithmetic mean and the median to account for strong deviations or skewed distributions. 
- **Refine the definition of an “active user”.** Clearly define which actions contribute to activity, such as viewing or editing documents, generating reports, tracking time, or even the number of clicks. 
- **Consider the working calendar.** While a 24-hour window is suitable for DAU, the number of working days in a week or month still affects WAU and MAU. In Jmix applications, this can be addressed using the Jmix Business Calendar, which supports working shifts, public holidays, and weekends. 

As you might expect, all these metrics can be applied not only to the system as a whole, but also to specific features or functional areas.  

## Collecting metrics with Jmix 

Let’s assume that, after proper business analysis, we have identified which system actions should be tracked. The next step is the technical implementation of business metrics such as DAU, WAU, MAU, and the corresponding stickiness indicators. How can Jmix help with this? 

In Jmix, application metrics are collected, exposed, and exported using the **Micrometer** library. Micrometer is part of Jmix’s observability and monitoring support and is the de facto metrics facade in the Java and Spring ecosystem. In practice, it provides a standard, vendor-neutral way to turn low-level application metrics into meaningful business insights. 

Jmix integrates Micrometer on top of **Spring Boot Actuator**, a Spring Boot module that offers production-ready features for monitoring and managing applications at runtime. This integration provides several benefits: 
- Automatic metrics for core Jmix components 
- Simple configuration through application.properties 
- Compatibility with Spring Boot’s built-in monitoring endpoints and metrics 
- Flexible configuring with the standard Spring mechanisms 

Out of the box, Jmix includes built-in metrics for its main structural units—**Views** and **Data Loaders**. This means that when you create screens and implement data-handling logic, you automatically gain the ability to monitor their behaviour without additional configuration. 

Supported lifecycle stages for **Views** include: 
Create, Load, Init, Before Show, Ready, Inject, Before Close, After Close. 

Supported lifecycle stages for **Data Loaders** include: 
Pre-load, Load, Post-load. 

Additional metrics can be introduced as needed by using the Micrometer API directly, for example by incrementing counters within event listeners that correspond to specific user actions. 

We plan to publish more technical articles that provide step-by-step guidance on configuring application metrics and the supporting monitoring infrastructure. In the meantime, you can explore the example below and consult the [Jmix AI Assistant](https://ai-assistant.jmix.io/), which is always ready to help with technical questions. 

## Metrics visualization  

Once application metrics are available, they can be exposed to monitoring tools immediately. While it is possible to build internal monitoring dashboards in Jmix using the [Charts add-on](https://www.jmix.io/marketplace/charts/), the more common approach is to rely on established observability tooling. 

A typical setup uses **Prometheus** for external metric collection and storage, and **Grafana** for visualisation. Both tools integrate seamlessly with Micrometer through Spring Boot Actuator, making them a natural choice for production environments. 

Jmix also provides ready-made [Grafana dashboards for Jmix](https://github.com/jmix-framework/jmix-grafana-dashboards) specifically designed for visualising application metrics. As a result, there is usually no need to introduce custom visualisation logic into the application itself. Instead, you can rely on existing infrastructure and well-established practices to analyse statistical and performance data. 

As mentioned earlier, **Views** and **Data Loaders** are available for monitoring out of the box. In Prometheus, these metrics are exposed using the following prefixes: 

- 'jmix_ui_views' — supported tags: 'lifeCycle', 'view' 
- 'jmix_ui_data' — supported tags: 'lifeCycle', 'view', 'dataLoader' 

These metrics can be used directly in Prometheus queries and Grafana dashboards to gain detailed insights into user interaction patterns and application behaviour. For example: 

```
jmix_ui_data_seconds_max{dataLoader="usersDl",lifeCycle="load",view="User.list",} 0.005668899 
```

## Metrics implementation for Active User Monitoring 

Now let’s return to the business metrics introduced at the beginning of this article. To demonstrate how they can be implemented in practice, we have prepared a [sample application](https://github.com/jmix-projects/jmix-app-usage-metrics-sample/) whose purpose is to register active users and calculate the corresponding metrics for Prometheus. 

Alongside the application source code, you will find several useful artefacts: 
- A **README** file that provides a detailed explanation of the implementation 
- Step-by-step instructions showing how to integrate these metrics into your own project 
- A ready-to-import **Grafana dashboard**, as well as a docker-compose file for quickly setting up the monitoring infrastructure 

For the sake of simplicity, this example assumes that a user is considered active as soon as they successfully log in to the system. To implement this logic, we rely on two Jmix add-ons: **Quartz** and **Jmix Business Calendar**. 

Our intermediate goal is to teach the application to expose metrics in the following format: 


```
#HELP active_users_dau The daily active users metric 
#TYPE active_users_dau gauge 
active_users_dau{application="business-metrics-app"} 2.0 
#HELP active_users_mau The monthly active users metrics 
#TYPE active_users_mau gauge 
active_users_mau{application="business-metrics-app", subtype="avg_dau"} 0.42105263471603394 active_users_mau{application="business-metrics-app", subtype="days_count"} 19.0 active_users_mau{application="business-metrics-app", subtype="main_value"} 4.0 
#HELP active_users_wau The weekly active users metrics 
#TYPE active_users_wau gauge 
active_users_wau{application="business-metrics-app", subtype="avg_dau"} 1.600000023841858 active_users_wau{application="business-metrics-app", subtype="days_count"} 5.0 active_users_wau{application="business-metrics-app", subtype="main_value"} 4.0 
```


As shown above, the exported metrics include: 
- DAU, WAU, and MAU values 
- Average DAU (metrics labelled subtype="avg_dau") 
- The number of actual working days in the period (metrics labelled subtype="days_count") 

As you may know,[ PromQL](https://grafana.com/blog/introduction-to-promql-the-prometheus-query-language/) is the primary query language used to retrieve and manipulate data for visualisations in Grafana. However, despite the apparent simplicity of the task, PromQL alone is not sufficient in this case for several reasons: 

- The active_users_dau metric is not a regular gauge. We are not interested in how DAU changes throughout the day; only the final daily value matters. 
- Time data must be properly formatted and aligned to allow aggregation by day. 
- Displaying active_users_wau, active_users_mau, average DAU, and stickiness on the same chart is not straightforward using PromQL alone. 

In our example, these challenges are addressed using Grafana’s powerful [Transformations mechanism](https://grafana.com/blog/you-should-know-about-transformations-in-grafana/). Transformations allow data to be reshaped into a form that best suits a specific visualisation without modifying the original data in the data source and without impacting the data source performance. This significantly extends the practical capabilities of PromQL and enables more advanced dashboards with minimal additional complexity. 

## Result 

In summary, we implemented a practical and flexible approach to analysing enterprise application usage, combining configurable working calendars with the powerful visualisation capabilities of Grafana. 

By building on standard monitoring tools such as Prometheus and Grafana, we achieved an effective solution for tracking usage efficiency in Jmix-based applications without adding unnecessary complexity. 

**Key benefits:** 
- **Business-relevant metrics** such as DAU, WAU, MAU, and stickiness derived from real user activity 
- **Flexible calendar awareness**, including working days, holidays, and shifts 
- **Minimal application overhead** by relying on Micrometer, Prometheus, and Grafana 
- **Rich visualisation and analysis** using ready-made dashboards and Grafana transformations 
- **Scalable and extensible architecture** based on industry-standard tooling 

This approach provides a solid foundation for understanding how enterprise systems are actually used and for making informed technical and business decisions.   

![]({{strapiUrl}}/uploads/mau2_324440bc52.png)
 ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Simplifying Process Automation of Public Services]]></title>
            <link>https://www.jmix.io/blog/simplifying-process-automation-of-public-services</link>
            <guid>https://www.jmix.io/blog/simplifying-process-automation-of-public-services</guid>
            <pubDate>Mon, 22 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/undefined_d57bd95ba3.jpeg">This tutorial explores Jmix BPM capabilities through a practical example: an art gallery website where artists can submit requests to take part in the upcoming event, backed by a collaborative, process-driven application that helps curators review submissions.]]></description>
            <content:encoded><![CDATA[Jmix BPM is an open-source platform that helps Java developers automate processes while avoiding complexities of BPM engine configuration. With a set of intuitive BPMN 2.0 visual tools it provides a user-friendly experience for creating, running, and testing business processes. 

This tutorial explores Jmix BPM capabilities through a practical example: an art gallery website where artists can submit requests to take part in the upcoming event, backed by a collaborative, process-driven application that helps curators review submissions.

![]({{strapiUrl}}/uploads/1_33a97cf1b4.webp)

In the course of the tutorial, you will: 
- Design and run a web site 
- Develop a backend application 
- Create and integrate a business process 

By the end of this tutorial, you'll be ready to develop your own process-driven application within a tight timeline, as a solo project or with a small team. 

## Jmix for sure. What else? 

As you start a project, you’ll likely find yourself asking questions and investigating tools. You might consider building a public-facing part using PHP or creating a Single Page Application with React. What about using Next.js for business logic? Which BPM engine would best suit your needs — Flowable or Camunda? Should it be a standalone or embedded solution? How will you manage production deployments effectively? Where should data be stored — on the BPM engine's side or in a separate backend? How to design process forms? 

![]({{strapiUrl}}/uploads/2_14480e5dd1.webp)

This can be overwhelming, but Jmix is here to make things manageable. However, Jmix alone won't cover everything. 

Overall, to complete this tutorial, you will need the following: 
 - IntelliJ IDEA with <a href="https://plugins.jetbrains.com/plugin/14340-jmix/" target="_blank">Jmix plugin</a>
- <a href="https://www.jmix.io/marketplace/rest-api/" target="_blank">Jmix REST API</a> and <a href="https://www.jmix.io/marketplace/bpm/" target="_blank">Jmix BPM</a> add-ons 
- <a href="https://grapesjs.com/" target="_blank">GrapesJS</a> (or your preferred tool for creating a website layout) 
- Docker Desktop to run NGINX web server image 

## Website Design 

Let’s begin with creating a public-facing part of the service. <a href="https://grapesjs.com/" target="_blank">GrapesJS</a> is a fantastic tool for creating visually appealing layouts without going deep into HTML and CSS.  

<div style="border: 1px solid #ccc; padding: 16px; border-radius: 6px;">
  GrapesJS is not limited to designing web sites; there are numerous other use cases. As a quick example, Jmix employs GrapesJS designer for its <a href="https://www.jmix.io/marketplace/message-templates/" target="_blank">message templates add-on</a>. 
</div>

With the WYSIWYG designer, you can see a live preview of a web page as you build it. No need to be a web design pro or have any special expertise to use this tool. 

![]({{strapiUrl}}/uploads/3_28336ff8c1.webp)

Similarly, there is no need to aim for perfection. It's easy to get caught up in making endless tweaks. At first, just focus on adding the fields needed for user input. 

The editor will let you view the source code: 

![]({{strapiUrl}}/uploads/4_389477ec16.webp)


Looking ahead, this page will communicate with the backend application. To make this work, include the following JavaScript snippet: 

```
<script> 

document.getElementById('sendRequestButton').addEventListener('click', function() { 

    // Get values from input fields 

    const name = document.getElementById('name').value; 

    const email = document.getElementById('email').value; 

    const portfolio = document.getElementById('portfolio').value; 

 

    // Prepare the request payload 

    const data = { 

        "request": { 

            name: name, 

            email: email, 

            portfolio: portfolio 

        } 

    }; 

 

    // Send POST request using Fetch API 

    fetch('http://localhost:8080/rest/services/public/create', { 

        method: 'POST', 

        headers: { 

            'Content-Type': 'application/json' 

        }, 

        body: JSON.stringify(data) 

    }) 

    .then(response => { 

        if (!response.ok) { 

            throw new Error('Network response was not ok'); 

        } 

        return response.json(); 

    }); 

}); 

</script> 
```

<div style="border: 1px solid #ccc; padding: 16px; border-radius: 6px;">
  Note that this code is simplified for demo purposes and is not suitable for production use without security improvements.
</div> 

## Running Web Server 

The page will be hosted on a NGINX web server running in a Docker container. For a straightforward yet thorough overview of using NGINX with Docker, check out the Docker blog. In short, you need to open Docker Desktop and run a few commands, starting with pulling the NGINX image:

```docker pull nginx k```

By default, NGINX looks for files to serve in the /usr/share/nginx/html directory within the container. To get our website files into this directory, we can use a mounted volume. This allows us to link a directory from our local machine and map it into the running container. That is, simply place the site content created with GrapesJS into a local directory, such as /GrapesJS-Demo/site-content, and map it to /usr/share/nginx/html in the running container: 

```
docker run -it --rm -d -p 8181:80 --name webserver -v ~/GrapesJS-Demo/site-content:/usr/share/nginx/html nginx 
```

![]({{strapiUrl}}/uploads/5_0c13628ac0.webp)

Once you run this command, Docker Desktop will confirm that the web server is running and that the local directory has been successfully mounted to the container. The website can be now  accessed at http://localhost:8181. 

![]({{strapiUrl}}/uploads/6_1b56ab37e3.webp)

## Backend Application 

The backend development is about to start. We'll start by creating the project and move forward step by step. Just be sure to install Jmix into your IDE beforehand.

## Create a Project 

Create a new Jmix project from the IntelliJ IDEA starting screen: 

![]({{strapiUrl}}/uploads/7_a0367dc49e.webp)

In the wizard, select "Full-Stack Application (Java)." 

![]({{strapiUrl}}/uploads/8_8d8cdce0fb.webp)

Note that this application template comes with its own web interface. That's on purpose – it will function as our submission management system. 

## Data Model 

Once the project loads all dependencies, create a JPA entity named PublicRequest. Use the entity designer to add attributes for the submission fields: name, email, and portfolio. Also, add attributes for the final decision and status to help supervisors manage submissions.

![]({{strapiUrl}}/uploads/9_222dd195dc.webp)

One small addition to make is to always set a default status value. You can easily do this by modifying the source code of the entity class. In the Designer, just switch to the Text tab and update the status attribute like this:

```
@Column(name = "STATUS") 
private String status = "new"
```

Now, return to the Designer tab and click Views in the top left corner. This will open the view creation wizard. In the first step, choose a view template to work with this entity: 

![]({{strapiUrl}}/uploads/10_d4cc9dbdbb.webp)

Choose **Entity List and Details views**, to create views to list of instances and to edit specific instance. Then, simply click through the wizard with all the default settings. Once that’s done, run the application to see it in the browser. The view is now available from the main menu:

![]({{strapiUrl}}/uploads/11_ee36c35a51.webp)

The list is currently empty. To make new submissions appear on the list, we will set up a REST controller. 

## REST controller 

REST controller will handle incoming requests and send them between the frontend and the backend. In Jmix there are <a href="https://docs.jmix.io/jmix/rest/business-logic.html" target="_blank">three options</a> for creating REST controllers: 
1. **Classic Spring-style REST Controller** – fully manual and verbose with maximum control for any intricate logic. 
2. **Using rest-services.xml** – ideal for quickly exposing backend logic without the need to build custom endpoints. 
3. **Using the <a href="https://www.jmix.io/marketplace/rest-api/" target="_blank">REST API Add-on</a>** – employs @RestService for service class and @RestMethod for endpoint method. Jmix automatically generates the REST controller logic. 

 The third approach is the cleanest and most straightforward, and it will be the one we choose to follow. Let’s approach it step-by-step. 

Create a new Spring Bean and name it _PublicService_. It’s good practice to put it inside a dedicated _service_ package. 

![]({{strapiUrl}}/uploads/12_21624e016e.webp)

In the code, replace the _@Component_ annotation for _@RestService(“public”)_. The _"public"_ is a part of the URL path for accessing the REST method, such as /rest/services/**public**/create.  

Next, declare a method to create requests and annotate it with @RestMethod. In the body of the method, add a stub so we can confirm that it’s functioning. Don’t worry, we’ll tackle saving the data next. The code is as follows:  

```
@RestService("public") 

public class PublicService { 

 

    private record Request(String name, String email, String portfolio) {} 

    private record ServiceResponse(boolean result, String responseMessage) {} 

 

    @RestMethod 

    public ServiceResponse create(Request request) { 

        ServiceResponse result = new ServiceResponse(true, 

            "New incoming request received from " + request.name()); 

        System.out.println(result.toString()); 

        return result; 

    } 

} 
```

## Public Access to Endpoint 

For obvious reasons, Jmix won’t allow access to the endpoint until the specific permission is granted. But for our art gallery event it’s perfectly fine for this endpoint to be public. After all, submitting a portfolio should be a simple process that doesn’t require users to sign up or log in. 

To allow unauthorized access to the endpoint, follow these steps: 

1. Add a new property to the `application.properties` file:

    ```properties
    # Configure resources allowed for anonymous access
    jmix.resource-server.anonymous-url-patterns = /rest/services/public/**
    ```

2. Edit the security configuration within the `ArtgalleryDemoSecurityConfiguration.java` class:

    ```java
    @Configuration
    public class ArtgalleryDemoSecurityConfiguration {

        @Bean
        @Order(JmixSecurityFilterChainOrder.CUSTOM)
        SecurityFilterChain publicFilterChain(HttpSecurity http) throws Exception {

            http.securityMatcher("/rest/**")
                .authorizeHttpRequests(authorize ->
                    authorize.anyRequest().permitAll()
                )
                .csrf(csrf -> csrf.disable())
                .cors(Customizer.withDefaults());

            JmixHttpSecurityUtils.configureAnonymous(http);

            return http.build();
        }
    }
    ```

This configuration enables unauthorized users to access the REST endpoint. It establishes a custom security filter chain that permits requests to /rest/**, disables CSRF protection, and enables CORS with default settings.  

<div style="border: 1px solid #ccc; padding: 16px; border-radius: 6px;">
  For guidance on configuring custom endpoints, please see the <a href="https://docs.jmix.io/jmix/security/custom-endpoints.html#custom-endpoints-security" target="_blank">documentation</a> or watch <a href="https://www.youtube.com/watch?v=dTzecz_Ukj0" target="_blank">this webinar</a> discussing Jmix Security.
</div> 

## Testing Endpoint 

Let’s run a quick test to see if the web server is communicating with the backend. Open the site, enter some values, and click the send button. 

![]({{strapiUrl}}/uploads/13_fe04d9fec4.webp)

Switch to the IDE. Check the output in the terminal to confirm receiving a request:

![]({{strapiUrl}}/uploads/14_4918375c8f.webp)

It’s good to see the submission come through, but we also need to save it in the database for later review. That's our next goal.

<div style="border: 1px solid #ccc; padding: 16px; border-radius: 6px;">
  If you encounter problems at this stage, adding the following property in the application.properties file can assist with troubleshooting: 
  
```logging.level.org.springframework.security = info``` 

Changing “info” to "debug" or "trace" will provide detailed information in the terminal about the ongoing processes.
</div> 

## Storing Incoming Data 

Inside the service package, let's create another service called _DataService_. The steps to create this service are the same as for _PublicService_.  The code is as follows:

```
@Service 

public class DataService { 

 

    private final DataManager dataManager; 

 

    public DataService(DataManager dataManager) { 

        this.dataManager = dataManager; 

    } 

 

    public void createPublicRequest(String name, String email, String portfolio) { 

        // creating a new Public Request entity based on incoming parameters from PublicService 

        PublicRequest newPublicRequest = dataManager.unconstrained().create(PublicRequest.class); 

        newPublicRequest.setName(name); 

        newPublicRequest.setEmail(email); 

        newPublicRequest.setPortfolio(portfolio); 

        dataManager.unconstrained().save(newPublicRequest); 

    } 

} 
```

The _createPublicRequest_ method creates a new _PublicRequest_ instance and sets its attributes. This process is handled through Data Manager – the primary Jmix interface for CRUD operations on entities.

<div style="border: 1px solid #ccc; padding: 16px; border-radius: 6px;">
  Take note of using the unconstrained Data Manager. This is a quick way to permit entity manipulations for unauthorized users, serving more as a shortcut we use for this demo rather than a standard practice. It is totally possible to implement more granular user permissions. 
</div>

Next, you'll need to inject _DataService_ service into the _PublicService_ we created earlier and call the method:

```
@RestService("public") 

public class PublicService { 

 

    private final DataService dataService; 

 

    public PublicService(DataService dataService) { 

        this.dataService = dataService; 

    } 

 

    private record Request(String name, String email, String portfolio) {} 

 

    private record ServiceResponse(boolean result, String responseMessage) {} 

 

    @RestMethod 

    public ServiceResponse create(Request request) { 

        ServiceResponse result = new ServiceResponse(true, 

            "New incoming request received from " + request.name()); 

        dataService.createPublicRequest(request.name, request.email, request.portfolio); 

        return result; 

    } 

} 
```

Now restart the application and try sending another submission. You should see both the confirmation in the terminal and a new table record. 

![]({{strapiUrl}}/uploads/15_5bd768d853.webp)

## Business Process 

With the website and backend now interacting, our next step is to ensure these interactions take place at certain moments within a business process. Doing so will help us build an efficient workflow. 

## Creating Process Diagram

<div style="border: 1px solid #ccc; padding: 16px; border-radius: 6px;">
  Be sure to install the BPM add-on as outlined in the prerequisites, as it includes essential tools for managing processes. After installation, restart the application. 
</div>

To create a business process, head to *Modeler* found in the BPM menu section. Use drag and drop to create this simple process diagram: 

![]({{strapiUrl}}/uploads/16_a8c0cf533b.webp)

Here are the elements you should place on the canvas from left to right, along with their meanings: 
- **Start Event**: Automatically initiates a process instance when a new request is submitted. 
- **User Task**: A human-managed task for reviewing the submitted request. (To change the task type to "User," select it and click the wrench icon.) 
- **Exclusive Gateway**: A decision point with two possible outcomes: "Approved" or "Rejected." 
- **Task (x2)**: These are meant for sending a notification based on the decision. 
- **End Event (x2)**: Mark the end of the flows. 

## Configuring Elements 

None of the elements are currently configured. Follow the instructions below to configure them one by one. 

**Start Event**

When starting a process manually initiating a process, you need the option to choose a **PublicRequest** instance to work on. Let’s configure the start event to display a simple dialog with a dropdown list of available instances. 

Select the **Start Event** element on the canvas. Use the right panel to configure its Form properties as shown: 

![]({{strapiUrl}}/uploads/17_3d0ca8c66b.webp)

If you're curious about the **publicRequest** process variable, this configuration does more than just create a dialog – it also generates a process variable that carries data from the **PublicRequest** entity through the process. 

Now, it’s **really important** to save your process! Otherwise, you might lose your progress since the next step will have us refresh the page. 

![]({{strapiUrl}}/uploads/18_4897e261d6.webp)

**User Task**

The start event uses a simple input dialog, but this task will use a dedicated view. Let’s return to Jmix Studio and create one using the **BPMN** process form template. 

![]({{strapiUrl}}/uploads/19_e62d8c0663.webp)

The view creation wizard will guide you through the process. Start by selecting “**Process form for entity instance**” as the form template and provide a meaningful name for the descriptor.

![]({{strapiUrl}}/uploads/20_d64cdc8802.webp)

On the next step, select the **publicRequest** process variable in the respective field: 

![]({{strapiUrl}}/uploads/21_f72ba3b6a6.webp)

No changes are needed for the remaining steps in the wizard, so feel free to click **Next** to move through them. As a result, you should see the new view added. 

![]({{strapiUrl}}/uploads/22_67476e0086.webp)

Essentially that is a standard Jmix view. The difference is that it has a few annotations that allow it to function as a form within the process.  

Return to the application and refresh the page so that the new view gets hot-deployed. This step is important to get it ready for integrating into the process. Refreshing will clear the canvas, but that has been accounted for. Just restore the model from the draft to continue. 

![]({{strapiUrl}}/uploads/23_c68556ffb6.webp)

Select the **User Task**. In the right panel set **Assignee** properties as shown: 

![]({{strapiUrl}}/uploads/24_ffa9333b15.webp)

To keep it straightforward, all tasks go to admin, the only user of the application.  

<div style="border: 1px solid #ccc; padding: 16px; border-radius: 6px;">
  More users can be added through the Users view. New users must be granted security permissions before they can access the application and participate in the process. Learn <a href="https://docs.jmix.io/jmix/security/index.html#roles-and-policies" target="_blank">more</a>. 
</div>

Lastly, set the process form properties. To guide this element to display the correct view, just enter its ID. 

![]({{strapiUrl}}/uploads/25_1522f9404a.webp)

**Exclusive Gateway**

The exclusive gateway doesn’t require any configuration by itself, but its outcomes must be configured. Click on the approval path arrow to define its name, condition source, and outcome. 

![]({{strapiUrl}}/uploads/26_2aec28c8e1.webp)

Set up the flow for rejecting submissions in a similar manner:

![]({{strapiUrl}}/uploads/27_020ca29a07.webp)

<div style="border: 1px solid #ccc; padding: 16px; border-radius: 6px;">
  Alternatively, you can designate the approval path as the default flow. This way the other will be used automatically whenever the approval fails. 
</div>

**Tasks for sending notifications**

To stay on track, sending notifications is not covered in this tutorial. However, to help you bring this functionality to your project, Jmix provides ready to use functionality for <a href="https://www.jmix.io/marketplace/notifications/" target="_blank">sending in-app notifications</a> and <a href="https://www.jmix.io/marketplace/email-sending/" target="_blank">emails</a>.

**End Events**

No additional configuration is needed. 

## Deploy the Process 

Once all the elements are configured, proceed to deploy the process. Click the **Deploy Process** button in the top right of the **Modeler** view. 

![]({{strapiUrl}}/uploads/28_f30acb6213.webp)

To verify successful deployment, see if the process appears on the **Process definitions** view

![]({{strapiUrl}}/uploads/29_ce42bd85cb.webp)

This view provides the option to manually start the process, but let’s make an extra effort to do this automatically.

## Autostart Process on New Submission 

A process instance can automatically start when a new submission is saved. To set this up, add a listener for the EntitySavingEvent for the PublicRequest entity. Use the Event Listener tool in the Entity Designer to generate it: 

![]({{strapiUrl}}/uploads/30_4418e5b76f.webp)

Jmix Studio will generate a Spring Bean for you. After that, include the logic to initiate a new process instance for incoming requests. The code is as follows:

```
@Component 

public class PublicRequestEventListener { 

 

    private final RuntimeService runtimeService; 

 

    public PublicRequestEventListener(RuntimeService runtimeService) { 

        this.runtimeService = runtimeService; 

    } 

    @EventListener 

    public void onPublicRequestSaving(final EntitySavingEvent<PublicRequest> event) { 

        if (event.isNewEntity()) { 

            Map<String, Object> variables = new HashMap<>(); 

            PublicRequest publicRequest = event.getEntity(); 

            variables.put("publicRequest", publicRequest); 

String businessKey = publicRequest.getName() + " " + publicRequest.getEmail(); 

            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("public-request-processing", businessKey, variables); 

        } 

    } 

} 
```

<div style="border: 1px solid #ccc; padding: 16px; border-radius: 6px;">
  Jmix Studio can help you with coding. Use the Code Snippets option in the upper tool panel and look for the BPM-related snippets. You’ll need the “Start process instance” snippet.

![]({{strapiUrl}}/uploads/31_106b10deda.webp)
</div>

## Running the Process 

It’s time to see the process in action start to finish. Just make sure to restart the application and the process is deployed – it must appear on the **Process definitions** view. Then ready, follow the steps. 

### Step 1: Submitting a request 

Open the registration form in your browser and enter the details for the imaginary artist. I’m using An Gella as my example. Then, click the **Send Request** button. 

![]({{strapiUrl}}/uploads/32_3cb73bd5aa.webp)

### Step 2: Request saved 

In the Jmix application, go to **Public** requests and see if An Gella’s request is on the list. This is also to confirm that the data is saved to the database.

![]({{strapiUrl}}/uploads/33_580867a30a.webp)

### Step 3: Process instance starts 

A process instance should have started as well. Go to the **Process Instances** view and filter for processes with the Completion state set to active. You should see the new process instance created to review An Gella’s submission. 

![]({{strapiUrl}}/uploads/34_12545a0784.webp)

Double-click on this instance to learn more. In the view that opens, switch to the **Diagram** tab to check the process state. 

![]({{strapiUrl}}/uploads/35_bd0dec0cfd.webp)

The highlighted element shows that the submission is now under review. 

### Step 4: User receives a task 

To keep it simple, we assigned **admin** to do the review, as the only user of the app. Take a look at **My Tasks** to see if it has been received. 

![]({{strapiUrl}}/uploads/36_11859d209a.webp)

### Step 5: Making decision 

As you open the task, you’ll see the artist's contact details along with the information they decided to share. Once you’ve reviewed it, you can leave a short comment and change the status. Clicking one of the buttons sends the application along one of the paths: approval or rejection. 

![]({{strapiUrl}}/uploads/37_a0e5a4a058.webp)

### Step 6: Process complete 

The process is now complete given the notification part was left unconfigured for this tutorial. But even if it was set up, it wouldn’t necessarily require user input, as automation is possible for most tasks in BPM. 

## Conclusion 

Let’s take a moment to go over the key points. So far, we have: 
- Created a website with GrapesJS tool for receiving incoming requests 
- Deployed the website to NGINX webserver 
- Created a backoffice Jmix application for processing requests 
- Created a REST controller 
- Implemented a service that stores the data 
- Designed and integrated a business process 

This tutorial may present a simplified scenario but lays a solid foundation for your future projects. With some dedication you can evolve it into a production-ready application in just a few weeks!  

<div style="border: 1px solid #ccc; padding: 16px; border-radius: 6px;">
  In case you prefer watching and listening over reading, check <a href="https://www.youtube.com/live/V30VMLkJdy8" target="_blank">the video version of this tutorial</a>. 
</div>

If you have any questions, feel free to start a topic in the <a href="https://forum.jmix.io/" target="_blank">community forum</a>, send us a message in the <a href="https://join.slack.com/t/jmixplatform/shared_invite/zt-2juulpoaf-7yp7F~m_fhFDmZ6GXHr83A" target="_blank">Slack channel</a>, or chat with the <a href="https://ai-assistant.jmix.io/" target="_blank">Jmix AI Assistant</a>. Keep going! 

**Useful links**
- <a href="https://www.youtube.com/live/V30VMLkJdy8" target="_blank">The video version of the tutorial</a>, in case you prefer watching and listening to reading.  
- <a href="https://grapesjs.com/" target="_blank">GrapesJS</a>, an open-source, multi-purpose, Web Builder Framework to build HTML templates without any coding knowledge. 
- <a href="https://www.docker.com/blog/how-to-use-the-official-nginx-docker-image/" target="_blank">How to use the NGINX Docker official image </a> 
- <a href="https://docs.jmix.io/jmix/bpm/index.html" target="_blank">Jmix BPM Docs</a> – all you need to build a process-driven web application powered by an open-source Flowable BPM engine with Jmix.
- <a href="https://docs.jmix.io/jmix/rest/index.html" target="_blank">Jmix REST API Docs</a> – a generic REST API that allows you to work with data, business services, and files without REST controllers’ boilerplate code.  




]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Optimizing Entity Persistence in Jmix]]></title>
            <link>https://www.jmix.io/blog/optimizing-entity-persistence-in-jmix</link>
            <guid>https://www.jmix.io/blog/optimizing-entity-persistence-in-jmix</guid>
            <pubDate>Fri, 19 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Data_Manager_Blog_1200h630_79299e7e4e.png">In this article, we explore how the DataManager#save() method works in Jmix and explain why reloading entities after saving is not always necessary.]]></description>
            <content:encoded><![CDATA[The DataManager#save(java.lang.Object...) method is one of the most frequently used methods of the DataManager component. Most Jmix projects end up calling it many times. However, there’s an important detail: this method reloads the entities being saved, which is not always useful. 

At the same time, a separate FetchPlan is generated for each entity based on the state of its fields at the time of saving, and each entity is reloaded individually. Therefore, saving 100 objects results in 100 additional reload queries (and potentially more, depending on entity complexity and the selected FetchPlan). What’s more, this process goes through the full ORM stack, including entity lifecycle events triggered during loading. 

If you want to avoid reloading entities, you can use the overloaded save() method that accepts a SaveContext and enable the setDiscardSaved(true) option.  

Not exactly convenient, is it? That’s why, starting with version 2.6, save(Object...) has a “twin” method: 

```
void saveWithoutReload(Object... entities); 
```

From its name and signature, it’s clear that this method is the more efficient choice when you need to save entities but don’t need to reload them afterwards. In many cases, it can significantly reduce load on the application server, the database, and the network. 

Let’s compare the code you’d write using SaveContext with the new method. Using SaveContext:

```
 dataManager.save(new SaveContext()  
    .saving(entity1,entity2)  
    .setDiscardSaved())  
```

You have to admit, the following code looks much nicer: 

```
dataManager.saveWithoutReload(entity1, entity2); 
```

The main advantage isn’t fewer lines of code, but an explicit choice of API method: whether you want the entities reloaded and returned after saving. This also lowers the risk of unfortunate mistakes. 
 
<img src="{{strapiUrl}}/uploads/Screenshot_2025_12_19_184417_003477cc9b.png" width="380" alt="good code"> 

On the one hand, it’s fair to say the change looks minor. But most performance problems come from database interactions, and finding and fixing them at the latest stages in the project is time-consuming and expensive. That’s why even a seemingly minor adjustment can save significant time and effort, while also improving the quality of the end product. 
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar What’s new in jmix 2.7]]></title>
            <link>https://www.jmix.io/blog/webinar-whats-new-in-jmix-2-7</link>
            <guid>https://www.jmix.io/blog/webinar-whats-new-in-jmix-2-7</guid>
            <pubDate>Wed, 19 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/What_s_New_in_Jmix_2_7_1080e1920_without_date_62de8c69df.png">This webinar covered the new features and enhancements in the latest version of Jmix and our roadmap for future updates.]]></description>
            <content:encoded><![CDATA[Release Jmix 2.7 is here, and we are glad to share more details about key updates to this new version with you!

We recommend reading an [article](https://www.jmix.io/blog/jmix-2-7-is-released/) about the release and watching a webinar recording below to learn about all the features.

Speakers of the webinar:

Gleb Gorelov, Tech lead
Konstantin Krivopustov, Head of Engineering
Viktor Fadeev, Product Manager

What we discussed:
- Product news:
  - Jmix on Vaadin Create
  - Jmix AI Manifest
  - Flowset Control app based on Jmix 
- New UI components:
  - Grouping Data Grid
  - User Menu
  - Card
  - Grid Layout
- Studio, Framework and Add-ons:
  - Role hierarchy and partial reverse engineering in Studio
  - Scalar and aggregate values in data repositories
  - Design-time reports

You can watch the recording of the workshop on our [YouTube-channel](https://www.youtube.com/live/oBnFD7fM-ow?si=WZjsNhlW4pRyyn8u).

<iframe width="560" height="315" class="b-youtube-player" src="https://www.youtube.com/embed/oBnFD7fM-ow?si=sYOCMVHQIQudyAv3" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Philosophy of Jmix in the AI Era]]></title>
            <link>https://www.jmix.io/blog/the-philosophy-of-jmix-in-the-ai-era</link>
            <guid>https://www.jmix.io/blog/the-philosophy-of-jmix-in-the-ai-era</guid>
            <pubDate>Mon, 17 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/AI_train_1200x600_a73d751666.png">The article highlights how the Jmix philosophy has evolved, the challenges LLMs pose for enterprise Java systems, why reliability matters more than code-generation speed, and the key insights from our 2025 R&D on Jmix’s AI direction.]]></description>
            <content:encoded><![CDATA[10 years ago, we presented <a href="https://www.jmix.io/cuba-blog/the-philosophy-of-the-cuba-platform/" target="_blank">the philosophy of the CUBA Platform</a>. Back then, the situation in Java development was very different. There was a broad variety of frameworks and tools in the Java SE world, without any clear mainstream technological leader. Five years ago, we identified Spring Boot as the winner of the Java technological race and invested development efforts in making it the platform’s core. This was how Jmix came into life, replacing the CUBA Platform. <a href="https://www.jmix.io/blog/jmix-the-future-of-cuba-platform/" target="_blank">In the Jmix introduction article</a>, we emphasized gaining a better developer experience, alignment with the most popular Java techs to date, making Jmix apps smaller, and maximizing application development productivity. 

Nowadays, we recognize how modern AI development tools are transforming the industry, disrupting what we used to call “development productivity”. Since the beginning of 2025, the Jmix team has conducted in-depth R&D to understand how Jmix can continue to bring value in the AI era. This document reflects the key findings of our research and highlights the engineering priorities of the Jmix team in adopting AI in the future.  

## Engineering is the Core Competence 

Generative AI has already become an integral part of our lives, transforming the way software is developed. In our view of the current state of the art, we share the perspective of Martin Fowler - one of the most influential figures in enterprise software development. While the current results are indeed impressive and promising, significant <a href="https://martinfowler.com/articles/202508-ai-thoughts.html" target="_blank">issues</a> related to the use of large language models (LLMs) remain that cannot be ignored. **AI amplifies both productivity and fragility**. Saving time on design and launch comes at the cost of heavier, more fragile systems that require more hardware and cost more to maintain. 

Software engineering, once largely deterministic, is now entering an era of tolerance margins and variability - much like civil or process engineering. The question is no longer “_Can AI write code_?” but rather “**_How do we ensure that code is safe, maintainable, and enterprise-grade?_**”. 

At Jmix, we embrace an engineering mindset - leveraging the best of AI to make rational, well-informed decisions throughout the software development process. 

## Reliability is the Core Principle 

In the AI era, Jmix is not just a high-productivity application development platform. It is the battle-proven architecture of how enterprise Java back-office systems should be built and maintained. With more than 10 years of successful implementation of Jmix as the foundation for multiple enterprise projects across various industries, it has proven to be a sustainable horizontal development technology. 
 

As AI amplifies both productivity and fragility, Jmix’s core values in the AI era can be defined as the following: 

1. **Predictable – Guardrails against AI chaos** 
Jmix applications follow a battle-proven architecture, ensuring that every component behaves as expected—no surprises at runtime, regardless of whether the code is written by humans or AI. 

2. **Interoperable – Built to integrate, not isolate** 
Developers integrate Jmix with enterprise systems, frameworks, and corporate LLMs. Jmix doesn’t replace your stack. It anchors it. 

3. **Consistent - Unified by design** 
Jmix enforces clear conventions and structure so that multiple developers and AIs can collaborate without drifting in style or approach.  

4. **Guarded - Secure and governed by default**  
From role-based access to server-side rendering, Jmix reduces the attack surface that AI-generated glue code might expand. 

5. **Sustainable – Built for the long run** 
Applications developed on Jmix age gracefully. Unlike prototype-driven projects that degrade over time, Jmix preserves long-term maintainability and reduces operational and technical debt. 

 

The reliability of the technological stack within Jmix remains a key priority for us. 

## Where We Invest in AI - and Where We Don’t 

Some development platforms rush to retrofit their IDEs with drag-and-drop UI builders for “AI productivity”. We see little value in doing this for Jmix Studio. 
 
Why? Because modern AI code agents already acquire deep context directly from a structured Jmix project. They don’t need Studio to imitate low-code tools that offer no real value. Jmix’s conventions are structured so AI tools can easily understand them. 
 
Instead, we focus our future engineering efforts on **AI features for the end-users of Jmix applications**, providing them with a dynamic and flexible workspace: 

- **Text-to-UI builder.** A personalized UI-design builder integrated into the Jmix app that enables end-users to prompt for the requirements and customize the UI at runtime. The changes will be implemented instantly.  

- **Zero-UI assistant.** A chat-based UI component embedded into the Jmix app eliminates the need to surf across disparate views to get the needed data or run some business logic. This should be a streamlined, straightforward, all-in-one enterprise tool. 

- **Text-to-Report builder.**  A new AI-powered wizard enables users to create reports using natural language descriptions. Users can now gain data insights while adhering to security constraints, without requiring additional involvement from system administrators.  

- **AI-assisted BPM modeling tool.**  Corporate AI agents can now act as digital coworkers within workflows, orchestrating tasks across humans, systems, and external AI services. They seamlessly integrate external data sources (APIs, corporate data lakes, knowledge bases) into processes without manual customization. 

- **Jmix-based tools for AI-agents.** Modern back-office apps don’t live in isolation. They must be accessible through Microsoft Teams, email, corporate messengers, or portals - wherever employees spend their time. Jmix aims to make this integration effortless and low-code-free, even by exposing Jmix apps as MCP servers so they can talk directly with corporate AI agents. 

 

All together, this makes us prioritize developing dynamic tools at app runtime, which will allow end-users to customize Jmix apps more easily and quickly. We believe that combining AI-assisted runtime tools with the robust Jmix enterprise architecture will make a giant leap in back-office automation. 

## Conclusion 

The next era of enterprise software won’t be about “faster CRUD” - AI has already trivialized that. It will be about: 
- Preventing expertise recession. 
- Embedding guardrails so AI doesn’t collapse enterprise IT into Shadow IT. 
- Empowering employees with smarter enterprise applications, without burdening developers with fragile prototypes or endless customizations. 
 
**Jmix is the platform that keeps enterprise development on the rails in the AI age.**
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Comparison low-code and less-code development platforms – Jmix]]></title>
            <link>https://www.jmix.io/blog/alternative-to-low-code-platforms</link>
            <guid>https://www.jmix.io/blog/alternative-to-low-code-platforms</guid>
            <pubDate>Thu, 13 Nov 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/alternative_to_low_code_platforms_1200h630_be540c1167.png">Low-Code (LCAP) is a leading enterprise development approach, and the Jmix team tracks its trends to pinpoint real business value, especially its ability to bridge business technologists and professional developers.]]></description>
        </item>
        <item>
            <title><![CDATA[Jmix 2.7 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-2-7-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-2-7-is-released</guid>
            <pubDate>Fri, 31 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/jmix_2_7_a463bb3855.png">Overview of the new features and important changes of the Jmix 2.7 feature release.]]></description>
            <content:encoded><![CDATA[We are pleased to announce the release of Jmix 2.7! This version introduces an updated Role Designer in Jmix Studio, new UI components, and includes a number of other framework improvements. You can view the full release notes at the <a href="https://docs.jmix.io/jmix/2.7/whats-new/index.html" target="_blank">What's New</a> section of the Jmix documentation.

Below is a brief look at the main new features of Jmix 2.7. 

## Visual Role Hierarchy Management

The **Role Designer** now offers a clear visualization of role inheritance hierarchies, allowing you to see how permissions flow from base roles. Inherited permissions appear as read-only elements, and the **Entities** tab uses intuitive color-coding: green for enabled and red for disabled elements. This simplifies the process of auditing and managing complex security configurations.

![role-designer.png]({{strapiUrl}}/uploads/role_designer_b623da9dd2.png)

## Add Attribute from DB

Check out the new **"Add attribute from DB"** option in the Entity Designer for database-first development.  Simply create a column in your database table, then import it directly into your Jmix data model as a mapped attribute. No more manual syncing—Studio takes care of the boring tasks.

![add-attribute-from-db.png]({{strapiUrl}}/uploads/add_attribute_from_db_e4574e7233.png)

## GroupDataGrid Component

The new `groupDataGrid` component can help you show your data more effectively.  This data grid enables row grouping based on one or more columns, ideal for summarizing and analyzing datasets. Install the **Grouping Data Grid** add-on and explore the <a href="https://docs.jmix.io/jmix/2.7/groupdatagrid/index.html" target="_blank">documentation</a> for quick integration.

![group-data-grid.png]({{strapiUrl}}/uploads/group_data_grid_3ef1dcffdc.png)

## Card Component

Meet the new `card` container component, perfect for presenting related content and actions in a polished, modular format. Customize its layout and styling to fit your design needs, whether for dashboards or detail views.

<img src="{{strapiUrl}}/uploads/card_cef08bff3c.png" width="510">

## GridLayout Component

Arrange components, cards, or fragments in a responsive two-dimensional grid with the `gridLayout`. Powered by CSS Grid Layout, it provides a flexible alternative to traditional data grids for complex, structured UIs that adapt seamlessly to different screen sizes. Plus, you can connect the `gridLayout` to a collection data container to render dynamic data sets.

![grid-layout.png]({{strapiUrl}}/uploads/grid_layout_8250263711.png)

## UserMenu Component

Enhance user interaction with the **userMenu** component, now included by default in new project templates. It displays the logged-in user alongside essential actions like "Substitute user" and "Log out" in a convenient dropdown. Add custom actions, nested items, or even other UI components for a tailored experience.

<img src="{{strapiUrl}}/uploads/user_menu_f816b1cf99.png" width="240">

## Date Filtering Enhancements

You can now filter by date easily with the "date equals" operation in `genericFilter` and `propertyFilter`. It ignores the time part, so you get the results within the date you’re looking for.

<img src="{{strapiUrl}}/uploads/date_equals_e24e0a70e1.png" width="723">

Plus, the **Date Interval** dialog now supports arbitrary start and end dates, replacing `>=` and `<` conditions with a single, intuitive control.

<img src="{{strapiUrl}}/uploads/date_interval_9af8404487.png" width="884">

## Data Repositories Enhancements

Data repositories in Jmix 2.7 became more powerful and convenient.

- **JmixDataRepository now extends ListCrudRepository**: all `findAll()` methods now return `List` instead of `Iterable`.
- **Support for Scalar Queries and Aggregates**: use `@Query` annotations to fetch scalar values or aggregates directly—perfect for metrics and summaries without full entity loads.
- **Pagination: Page vs. Slice**: stick with `Page` for full pagination info (including a COUNT query), or use the new `findAllSlice()` for lighter `Slice` results that skip the count, reducing database load.
- **New delegates for easier repository usage**: invoke repositories in views with `loadFromRepositoryDelegate` and `totalCountByRepositoryDelegate`, that save you from explicit `LoadContext` conversions. These delegates are generated automatically when using data repositories in the View Creation Wizard.

## Design-Time Reports

The Reports add-on now allows you to define report structures in Java classes at design time. Among the benefits: report definitions can be managed in version control (Git), you can debug report logic in your IDE, and updates propagate seamlessly across deployments. 

Note that this approach prioritizes developer control but disables runtime modifications by end-users. 

See examples in the See examples in the <a href="https://docs.jmix.io/jmix/2.7/reports-guide/index.html" target="_blank">Report Generation Guide</a>.

![design-time-reports.png]({{strapiUrl}}/uploads/design_time_reports_96e38bd47d.png)

## REST DataStore

The REST DataStore add-on now supports **sharing of entities and service interfaces** between integrated applications. This reduces code duplication and development efforts, but might cause tighter coupling between the applications.

## Updated Dependencies

The Vaadin framework has been updated to version 24.9.

## Future Plans

The next feature release is expected in February 2026. We're planning to do the following:

- Upgrade the technology stack to Spring Boot 4, Vaadin 25, EclipseLink 5
- Release SAML add-on
- Implement visualization of data model in a running application

## Conclusion

Jmix 2.7 marks another step forward in making enterprise development easier and more efficient.

If you have a question, want to share feedback, or simply connect with others, join us on the <a href="https://forum.jmix.io/" target="_blank">forum</a> or <a href="https://join.slack.com/t/jmixplatform/shared_invite/zt-2juulpoaf-7yp7F~m_fhFDmZ6GXHr83A" target="_blank">Slack</a>.

Thanks to all in the community for your helpful input. We hope Jmix 2.7 helps your projects be even more successful!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Validation in Java Applications: The Definitive Guide]]></title>
            <link>https://www.jmix.io/blog/validation-in-java-applications-the-definitive-guide</link>
            <guid>https://www.jmix.io/blog/validation-in-java-applications-the-definitive-guide</guid>
            <pubDate>Thu, 23 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Java_bin_validation_1200x630_eng_5397bed3e5.png">In this article, we are going to look at various approaches to validation in Jmix applications, from simple JPA annotations to advanced techniques that use Entity Listeners. Even though the examples are based on Jmix, the majority of the discussed approaches are applicable to any Spring Boot application with JPA and Bean Validation.]]></description>
            <content:encoded><![CDATA[Validation of data in enterprise applications often turns out to be spread across the entire codebase: JavaScript checks at the client side, in the screen controllers, business logic, database triggers and constraints. When the requirements change (and they change all the time), it becomes a real headache to keep finding and updating all the validation points. As a result, we have a combination of uncoordinated check-ups, snarled code, and potential bugs. Just ask yourself if there is a way to centralize validation, as well as to make it declarative and reusable.   

The answer is: "Yes", and it has been standardized for quite some time in the Java ecosystem. It is called Bean Validation. Validation is implemented in such a way that you can:   
- Define the rules once and apply them everywhere (business logic, Jmix UI, REST API, gRPC, etc)  
- Use the declarative approach instead of the imperative 'if-else' code pattern 
- Receive automated validation in the UI and the REST API without writing additional code  
- Work with the standards 

In this article, we are going to look at various approaches to validation in Jmix applications, from simple JPA annotations to advanced techniques that use Entity Listeners. Even though the examples are based on Jmix, the majority of the discussed approaches are applicable to any Spring Boot application with JPA and Bean Validation.  

## Database-level validation via JPA annotations

The most widespread way of validating the data is to use constraints at the database level: the **NOT NULL** flag, the string length, and unique indexes.  

Such an approach is especially important for enterprise applications focused on data processing. However, developers often make the same mistake of specifying the same constraints separately for each application level. Let's look at an example, which many will find familiar: the specification requires that the passport serial number should contain 10 characters. This constraint is implemented by everyone: the database architect in DDL, the backend developer in the `Entity` and in the REST API, and the frontend developer in the UI. Then the requirement is changed, and now the field is required to contain 15 characters. The DevOps updates the constraint in the database, but at the client side the restriction remains unchanged...   

The solution is obvious: validation has to be centralized! In **Jmix**, such validation is defined in the JPA annotations belonging to entities. The framework generates a correct DDL script based on those annotations and applies the corresponding validations at the client side.  

![]({{strapiUrl}}/uploads/image1_fda7859c75.png)

As the annotations are altered, Jmix Studio will update the DDL scripts and generate migrations scripts. At the next deployment, the new constraints will be applied to the UI, backend, and database at the same time.   

**Limitations of this approach:** JPA annotations work only for simple cases, which can be represented via standard DDL, such as NOT NULL, String length or field uniqueness. Using `@UniqueConstraint` you can define a unique constraint for a combination of several columns. But more complex logic, such as range validation, regular expressions, or custom business rules, requires a different approach, which is known as **Bean Validation**.  

## Bean validation  

It is considered a good practice to follow the standards that boast a long lifecycle, since their efficiency has been proven over thousands of projects. Java Bean Validation is an approach formulated in JSR 380, 349, and 303 and implemented in Hibernate Validator and Apache BVal. Its modern versions are developed as Jakarta Validation (the current version is 3.1).  

Even though a lot of developers are familiar with this solution, it is often underestimated. It is a simple way of building data validation even into legacy projects and of making those checks simple, easily understood, reliable and as close to business logic as possible.  

Using Bean Validation gives the project plenty of benefits:  
- Validation logic is located close to the subject matter: we define field and bean method constraints in the most natural, object-oriented way.  
- The Bean Validation standard gives us scores of validation annotations out of the box, such as: `@NotNull`, `@Size`, `@Min`, `@Max`, `@Pattern`, `@Email`, and `@Past`, as well as Hibernate-specific `@URL` and `@Length`, an extremely powerful `@ScriptAssert` and a lot of others.  
- The standard doesn't force us to use only the ready-made annotations; instead, it allows us to create our own. We can create a new annotation by combining a few others, or we can define it using a separate Java class as its validator.   
- Constraints can be placed only on fields or classes, but also on methods and their parameters. This approach is called **validation by contract** and will be discussed below.  

When the user submits the entered data, Jmix starts Bean Validation automatically, so the error message is displayed immediately, if the validation didn't pass. Therefore, you don't have to run the bean validators manually.  

But let's go back to the passport number example, and this time we are going to augment it with some constraints applied to the `Person` entity:  
1. The `name` field value must consist of two or more characters and be correct (the regular expression should match *Charles Ogier de Batz de Castelmore Comte d'Artagnan but reject R2D2*);  
2. The `height` field value should fall within the following range: 0 < height <= 300 cm;  
3. The `email` field should contain a string value matching the correct format for an email address.  

The `Person` class will look as follows when we add all the necessary checks:  

```
@JmixEntity  
@Table(name = "PERSON")  
@Entity  
@ValidPassportNumber(groups = {Default.class, UiCrossFieldChecks.class})  
public class Person {  
@JmixGeneratedValue  
@Column(name = "ID", nullable = false)  
@Id  
private UUID id;  
@InstanceName  
@Pattern(  
          	message = "Badly formed person's name: ${validatedValue}",  
          	regexp = "^[A-Z][a-z]*(\\s(([a-z]{1,3})|(([a-z]+')?[A-Z][a-z]*)))*$"  
)  
@NotNull  
@Size(min = 2)  
@Column(name = "NAME", nullable = false)  
private String name;  
@Email(  
        	message = "Email address has an invalid format: ${validatedValue}",  
        	regexp = "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$"  
)  
@Size(max = 120)  
@Column(name = "EMAIL", length = 120)  
private String email;  
@DecimalMax(value = "300", message = "Person's height can not exceed 300 centimeters")  
@DecimalMin(value = "0", inclusive = false, message = "Person's height should be positive")  
@Column(name = "HEIGHT")  
private BigDecimal height;  
@NotNull  
@Column(name = "COUNTRY", nullable = false)  
private Integer country;  
@NotNull  
@Size(min = 15, max = 15)  
@Column(name = "PASSPORT_NUMBER", nullable = false, length = 15)  
private String passportNumber;  
   // … getters & setters  
}  
```
The way we use the standard annotations here, such as `@NotNull`, `@DecimalMin`, or `@Pattern`, is intuitive. Let's look more closely at the `@ValidPassportNumber` annotation implementation. 

Our `@ValidPassportNumber` annotation checks that `Person#passportNumber` matches the regular expression template for each country specified in the  `Person#country` field.  

First of all, let's take a look at the documentation (Jmix or Hibernate manuals will do fine). According to the documentation, we have to annotate our class with this new annotation and pass the `groups` parameter into it, where `UiCrossFieldChecks.class` means that this validation has to be applied during the cross-validation stage, after the checks done on every individual field, which `Default.class` keeps the constraint in the default validation group unchanged.  

The annotation description looks like this  

```
@Documented  
@Target(ElementType.TYPE)  
@Retention(RetentionPolicy.RUNTIME)  
@Constraint(validatedBy = ValidPassportNumberValidator.class)  
public @interface ValidPassportNumber {  
String message() default "Passport number is not valid";  
Class<?>[] groups() default {};  
Class<? extends Payload>[] payload() default {};  

}  
```

Here, `@Target(ElementType.TYPE)` tells us that the objective of this runtime annotation is a class, and `@Constraint(validatedBy = ... )` defines that the check is carried out by the `ValidPassportNumberValidator` class, which implements the `ConstraintValidator<...>` interface. The validation code as such is located in the `isValid(...)` method, which actually does the checking: 

```
public class ValidPassportNumberValidator implements ConstraintValidator<ValidPassportNumber, Person> {  
@Override  
public boolean isValid(Person person, ConstraintValidatorContext ctx) {  
    	if (person == null) return false;  
    	if (person.getCountry() == null || person.getPassportNumber() == null) return false;  
    	boolean ok = doPassportNumberFormatCheck(person.getCountry(), person.getPassportNumber());  
    	if (!ok) {  
        	ctx.disableDefaultConstraintViolation();  
        	ctx.buildConstraintViolationWithTemplate(  
                        	"Passport number '" + person.getPassportNumber() +  
                                	"' does not match the required format for country " + person.getCountry()  
                	)  
                	.addPropertyNode("passportNumber")  
                	.addConstraintViolation();  
    	}  
    	return ok;  
}  
private boolean doPassportNumberFormatCheck(Country country, String passportNumber) {  
    	// passport format check  
}  
}
```
And that's it. With Jmix Framework we don't have to write anything except this piece of code: the custom validation works, and it will display the error message for the user. No rocket science, is it?  

Now let's see how it actually works. Jmix has a convenient feature: the platform not only displays the error message for the user, but also highlights the fields in red, if they didn't pass the validation:  

![]({{strapiUrl}}/uploads/image2_42b1a3f37a.png)

This is quite an elegant solution, isn't it? You receive an adequate visualization of the validation errors in the UI, and all you need to do is to add a couple of Java-annotations to the domain entities.  

To sum up this section, let's briefly enumerate the entity Bean Validation benefits:  
1. It is readable and easy to understand. 
2. It allows us to set the value constraints in the entity classes directly.  
3. It can be configured and expanded.  
4. It is integrated into ORMs, and the checks are run automatically long before storing the changes into the database. 
5. Frameworks like Jmix run bean validation automatically when the user submits the data into the UI (and if it doesn't, invoking the Validator's interface manually is not hard).  
6. Bean Validation is a universally accepted standard, well documented by internet resources.  

But what to do when you need to set constraints on a method, a constructor, or a REST address to validate the data coming from an external system? Or in case you need to validate the values of method parameters declaratively without writing boring code with multiple if-else conditions in each validated method?  

The answer is easy: Bean Validation is applicable to methods, as well!  

## Validation by contract  

Sometimes we need to go beyond the data model state validation. Quite a lot of methods could benefit from automated parameter validation and from the returned value. This could be necessary not just for data validation before letting it go to REST or SOAP addresses, but also when we want to define preconditions and postconditions for method invocations to ensure that the input data is validated before the method body is executed, or that the return value fits within the expected range. Another example is when we describe the input parameter ranges declaratively to improve code readability.   

With bean validation, the constraints can be applied to input parameters and to returned values from methods and constructors to validate the preconditions and postconditions applied to their invocations by any Java class. This approach has several advantages in comparison with the traditional ways of validating the parameter and return value correctness: 
- No need to carry out the checks manually using the imperative style (e.g., by throwing an `IllegalArgumentException` or something similar). It is possible to define the constraints declaratively, thus making the code easier to understand and more expressive.  
- The constraints can be set up differently, reused, and configured: there is no need to write up the validation logic for every check.  Less code means fewer bugs.  
- If a class, a method return value or a parameter are annotated with `@Validated`, the checks will be automatically carried out by the platform at every method invocation.  
- If an executable module is annotated with `@Documented`, its preconditions and postconditions will be included into the generated JavaDoc.

Using validation by contract we receive easily understood, concise and highly maintainable code.  

As an example, let's consider a REST service from a Jmix application. The `PersonRestService` service allows us to get a list of people's names from the database using the `allPersonNames()` and also to add a new person by calling `addNewPerson(...)`.  

Not to forget that bean validation can be inherited! In other words, if we annotate a class, a field, or a method, then all classes that extend this class or implement this interface will inherit the same validation annotation. 

```
@Validated  
@RestService("jmixapp_PersonApiService")  
public class PersonRestService {  
private final DataManager dataManager;  
public PersonRestService(DataManager dataManager) {  
    	this.dataManager = dataManager;  
}  
@NotNull  
@RestMethod(httpMethods = RestHttpMethod.GET)  
public List<@NotBlank String> allPersonNames() {  
    	return dataManager.load(Person.class)  
            	.all()  
            	.list()  
            	.stream()  
            	.map(Person::getName)  
            	.toList();  
}  
@Transactional  
@RestMethod(httpMethods = RestHttpMethod.POST)  
public void addNewPerson(  
        	@NotNull  
        	@Size(min = 2, max = 255)  
        	@Pattern(  
                	message = "Bad formed person name: ${validatedValue}",  
                	regexp = "^[A-Z][a-z]*(\\s(([a-z]{1,3})|(([a-z]+')?[A-Z][a-z]*)))*$"  
        	) String name,  
        	@DecimalMax(value = "300", message = "Person height cannot exceed 300 centimeters")  
        	@DecimalMin(value = "0", inclusive = false, message = "Person height should be positive")  
        	BigDecimal height,  
        	@NotNull Integer countryCode,  
        	@NotNull @Size(min = 15, max = 15) String passportNumber  
) {  
    	var person = dataManager.create(Person.class);  
    	person.setCountry(Country.fromId(countryCode));  
    	person.setHeight(height);  
    	person.setName(name);  
    	person.setPassportNumber(passportNumber);  
    	dataManager.save(person);  
}  
}
```
It is important to note that AOP doesn't work inside the self-invocations of its own methods, so we should be careful while working with `@Validated` – sometimes it can create bugs in production, if we don't track the AOP transaction sequences appropriately. This applies not only to validation, but to transactions themselves, as well. It is always possible to call a validation manually by injecting the required Spring Bean by its qualifier from the Spring context and calling `validator#validate()`; on it. As an alternative, we can just delegate the required code snippet into another Spring Component. 

This code is specific for the Jmix Framework, which exposes an ordinary Spring Service as a REST controller and passes the parameters and the method return value using the @RestService annotation (an alias for the common `@Service)` and `@RestMethod`. However, if you don't like this approach, you can use ordinary REST controllers, which, in turn, represent the commonly used approach to exposing REST in Spring.  

Thus, the `@Valid` annotation determines that each object in the collection returned by the `allPersonNames()` method has to be validated also for matching the `@NotBlank` constraint.  

In a Jmix application, these methods are available at the following URL paths:  
- `/rest/services/jmixapp_PersonApiService/allPersonNames`   
- `/rest/services/jmixapp_PersonApiService/addNewPerson`  

To understand working with Business Logic REST in detail, we advise you to take a look at the following [documentation](https://docs.jmix.io/jmix/rest/business-logic.html#exposing-a-service).

![]({{strapiUrl}}/uploads/image3_99027fe0b5.png)

As you have probably noticed, in the example above the passport number and other parameters of the Person entity are not validated at the cross-validation stage. This is because these fields require cross-validation of the `addNewPerson` method parameters, since the choice of the `passportNumber` regular expression template depends on the `country` field value. Such cross-validation is a complete analogy of an entity constraint at the class level!  

Cross-validation for parameters is supported in JSR 349 and 380. You can take a look at the [Hibernate](https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-cross-parameter-constraints) documentation to learn how to implement your own cross-validation for class/interface methods.  

What other options for data validation are there?  
- Generic REST Entity API: Jmix has a REST API for entities out of the box, and validation is applied automatically to all fields annotated for validation 
- Spring REST Controller: Standard for any Spring Boot application  
- Any other Spring Component annotated with `@Validated`.  
- Manual usage: we validate any object via the Validator from the Spring DI Context. It is possible to receive `validatorBean` and call `validator.validate(object)`, or you can configure the Validator on your own.  

Whatever you choose, it is the same unified mechanism intended for checking the data for validity.  

## Validation pitfalls  

We could confidently say that validation of time-related data is one of the most insidious areas in Java applications. The problems often show themselves only in production when the server works in one time zone, and the clients live in another, or the developers tested it all under Windows, but then deployed it to Linux. Let's take a look at the problems and their solutions.  

### Problem with @PastOrPresent on different OS's

The key problem is related to the difference in system clock accuracy on Windows and Linux. Linux supports highly accurate timers with resolutions up to nanoseconds, whereas Windows historically works with accuracy from 1 to 15 milliseconds. This causes a situation where the `@PastOrPresent` validation can behave unpredictably:  

- On Linux, the times values almost universally differ even between the consequent `LocalDateTime.now()` calls 
- On Windows, both calls can hit the same "tick" of the system clock and return the same value  

**Solution:** Use a custom validator with an acceptable margin of error:  

```
@Target({ElementType.FIELD, ElementType.PARAMETER})  
@Retention(RetentionPolicy.RUNTIME)  
@Constraint(validatedBy = PastOrPresentWithToleranceValidator.class)  
public @interface PastOrPresentWithTolerance {  
long milliseconds() default 100;  
String message() default "Date must be in the past or present (with tolerance)";  
Class<?>[] groups() default {};  
Class<? extends Payload>[] payload() default {};  
}  
public class PastOrPresentWithToleranceValidator  
    	implements ConstraintValidator<PastOrPresentWithTolerance, LocalDateTime> {  
private long toleranceMs;  
@Override  
public void initialize(PastOrPresentWithTolerance annotation) {  
    	this.toleranceMs = annotation.milliseconds();  
}  
@Override  
public boolean isValid(LocalDateTime value, ConstraintValidatorContext context) {  
    	if (value == null) return true;  
    	LocalDateTime now = LocalDateTime.now();  
    	LocalDateTime nowWithTolerance = now.plus(toleranceMs, ChronoUnit.MILLIS);  
    	return value.isBefore(nowWithTolerance) || value.equals(nowWithTolerance);  
}  
}
```
This  "tolerant" validator can turn out to be an acceptable working solution, though there are better alternatives: 

- Use `ClockProvider` and define "now" in a centralized way (for tests, you are allowed to "freeze" time);  
- Where possible, validate Instant (UTC) for technical labels.   

Anyway, you should always keep in mind that when we are comparing two date/time values in business logic, we have to be careful with such code.

### The time zone issue

`LocalDate` and `LocalDateTime` contain no information about the time zone, which can cause validation errors when the server and the client are located in different time zones.  

Example:  
- The server is in UTC; the time is 11:30 pm; the date is 2025-09-30  
- The client is in Istanbul (GMT+3); the time is 02:30 am; the date is 2025-10-01  
- The client sends the "today's" date; the server considers it "a future date"  

**Solution:** Take the time zone into account in the validator:  

```
@Component  
public class FutureOrPresentClientZoneValidator  
    	implements ConstraintValidator<FutureOrPresentClientZone, LocalDate> {  
@Autowired  
private CurrentAuthentication currentAuthentication;  // Jmix компонент  
@Override  
public boolean isValid(LocalDate date, ConstraintValidatorContext context) {  
    	if (date == null) return true;  
    	if(currentAuthentication.getAuthentication() == null) throw new IllegalStateException("No authentication");  
    	// Getting the user's time zone  
    	TimeZone userTimeZone = currentAuthentication.getTimeZone();  
    	ZoneId clientZone = userTimeZone.toZoneId();  
    	// Calculating "today" in the client's time zone  
    	LocalDate todayForClient = LocalDate.now(clientZone);  
    	return !date.isBefore(todayForClient);  
}  
}  
```
### The date cross-validation problem

Cross-validation takes place when several fields in the same form or object have to be validated together. The classical example is the date range where the start date should be earlier than the end date.  

**Anti-pattern:**

```
// Validation in the controller - code duplication  
if (order.getStartDate().isAfter(order.getEndDate())) {  
throw new ValidationException("Start date must be before end date");  
}  
```
**Correct solution: class-level validation:**

```
@ValidDateRange  // Custom annotation at the class level  
public class DateRangeRequest {  
private LocalDate startDate;  
private LocalDate endDate;  
}  
@Target({ElementType.TYPE})  
@Retention(RetentionPolicy.RUNTIME)  
@Constraint(validatedBy = DateRangeValidator.class)  
public @interface ValidDateRange {  
String message() default "End date must be after start date";  
Class<?>[] groups() default {};  
Class<? extends Payload>[] payload() default {};  
}  
public class DateRangeValidator implements ConstraintValidator<ValidDateRange, DateRangeRequest> {  
@Override  
public boolean isValid(DateRangeRequest value, ConstraintValidatorContext context) {  
    	if (value.getStartDate() == null || value.getEndDate() == null) {  
        	return true; // Letting @NotNull process null values  
    	}  
    	if (value.getStartDate().isAfter(value.getEndDate())) {  
        	context.disableDefaultConstraintViolation();  
        	context.buildConstraintViolationWithTemplate(  
                        	"Start date " + value.getStartDate() +  
                                	" cannot be after end date " + value.getEndDate())  
                	.addPropertyNode("startDate")  // Binding the error to a particular field  
                	.addConstraintViolation();  
        	return false;  
    	}  
    	return true;  
}  
}
```
### Choosing the correct date type  

Here are some brief recommendations for choosing the date types to work with dates:  
- **LocalDate** — for dates without time (birthdays, document issues dates)  
- **LocalDateTime** — for local events in the same time zone  
- **Instant** — for technical time labels (created_at, updated_at), UTC  
- **ZonedDateTime** — for business logic that takes time zones into account  
- **OffsetDateTime** — for APIs and integrations, ISO 8601 support 
- Avoid **java.util.Date** — it's a legacy type, use `java.time.*` instead  

### Other frequent problems  

**`@Temporal` with new date types**: The `@Temporal` annotation is not needed and doesn't work with `java.time.*` types.

```
// Incorrect  
@Temporal(TemporalType.TIMESTAMP)  
private LocalDate eventDateError;  // Error!  

// Correct  
@Column(name = "EVENT_DATE")  
private LocalDate eventDateOk;  // Automatically maps to SQL DATE
```

**Choosing a correct annotation for strings:**  

- `@NotNull` — only to check for a null value  
- `@NotEmpty` — not a null and length > 0  
- `@NotBlank` — not a null and not only spaces (the behavior you need in most case)  

To summarize the pitfalls inside Bean Validation: be always careful with what you are writing. Remember that JPA annotations are not some magic; it is concrete code with underlying business rules.  

## Beyond bean validation  

The world knows no perfection, and bean validation has its own fair share of drawbacks and limitations:  

1. Sometimes we just need to check the condition of a complicated object graph before storing the changes into the database. For example, we need to ensure that all items from the customer's order fit inside the same parcel. It is quite a complex operation and doing it every time the user adds new items to the order is not a good idea. Therefore, this validation might be necessary only once: before we store the `Order` object and its `OrderItem` sub-objects into the database.  
2. Some validations have to be applied inside a transaction. For instance, the e-store system has to check whether there are enough copies of the product in stock to fulfill the order before it is committed to the database. This validation can be done only inside the transaction, since the system is multithreaded and the amount of a certain product in stock can be changed at any moment.   

Jmix offers two mechanisms for data validation before transaction commit, which are called [Entity Listeners](https://docs.jmix.io/jmix/data-access/entity-events.html) and Transaction Listeners. Let's review them in detail.  

### Entity listeners  

[Entity listeners](https://docs.jmix.io/jmix/data-access/entity-events.html) in Jmix are similar as a concept to JPA lifecycle callbacks (). Both mechanisms allow us to validate entity objects before and after they are stored in the database.  

Jmix allows us to create and enable an entity listener easily. To do that, you need to create a manageable Spring Component and add methods to it annotated with `@EventListener` with one of the following three types of parameter events:  
- `EntityLoadingEvent<YourEntity>`   
- `EntitySavingEvent<YourEntity>`   
- `EntityChangedEvent<YourEntity>`  

The easiest way to do that is to use the Jmix Studio Context Menu → the **Event Listeners** button. 

![]({{strapiUrl}}/uploads/image4_e9cdbc27f1.png)

The resulting autogenerated Event Listener looks as follows:

```
@Component  
public class PersonEventListener {  
@EventListener  
public void onPersonLoading(final EntityLoadingEvent<Person> event) {  
// called during fetching from the database  
}  
@EventListener  
public void onPersonSaving(final EntitySavingEvent<Person> event) {  
   	// called before storing into the database  
}  
@EventListener  
public void onPersonChangedBeforeCommit(final EntityChangedEvent<Person> event) {  
  	// called after the change but BEFORE the transaction commit  
}  
}  
```

**An important aspect of `EntityChangedEvent`** is that this event can be handled in two ways:  

With the `@EventListener` annotation — the handler is called **BEFORE** the transaction commit, and changes are applied in the same transaction. You can change the data, and it will be included in the same commit. If an exception is thrown, everything will be rolled back.  

With the `@TransactionalEventListener` annotation — the handler is called **AFTER** the transaction commit, so, you have to start a new transaction explicitly via `@Transactional(propagation = Propagation.REQUIRES_NEW)`. Exceptions thrown in such a handler will not roll back the main transaction.  

Example of after-commit handling:  

```
@Component  
public class PersonEventListener {  
@TransactionalEventListener  // By default phase = TransactionPhase.AFTER_COMMIT  
@Transactional(propagation = Propagation.REQUIRES_NEW) // если пишим в БД  
public void onPersonChangedAfterCommit(final EntityChangedEvent<Person> event) {  
    	try {  
        	// Working with the data in the new transaction  
        	// Exceptions thrown here won't affect the main transaction  
    	} catch (Exception e) {  
        	log.error("Error handling Person changes after commit", e);  
    	}  
}  
}  
```
Also, Jmix supports [soft delete](https://docs.jmix.ru/jmix/data-model/soft-deletion.html) — an approach which, instead of really deleting records from the database, only marks them as deleted, after which they become inaccessible for a common user. For the soft delete, the platform invokes `EntityChangedEvent` listeners with the `DELETED` type.   

To summarize, entity listeners are an excellent choice if:  
- It is required to carry out the data validation inside a transaction before the entity object is stored into the database  
- It is required to check the database data during validation, for example, check that there is enough product in stock to accept the order  
- You have to pay attention not only to the context root entity object like Order but also to the objects related to it, e.g. `OrderItems`  
- We would like to trace the `INSERT`, `UPDATE` and `DELETE` operations for some entity classes only, for example, only for `Order` and `OrderItem`, and we don’t need to check the changes in other classes within the transaction   

## Transaction listeners  

Jmix transaction listeners also work in the transaction context, but, unlike entity listeners, they are called for **each** database transaction.  

It gives them superpower:  
- Nothing can escape their attention  

But it also brings about some drawbacks:  
- They are harder to write 
- They can reduce the performance drastically  
- They must be written very carefully: a bug in a transaction listener can hinder even the initial application load-up   

To sum up, transaction listeners are a good solution, when you need to inspect different entity types using the same algorithm, e.g., check all data for cyber-fraud using a unified service that serves all business objects owned by you. 

![]({{strapiUrl}}/uploads/image5_5e78a8fb8f.png)

Look at the following sample that checks whether the entity has the `@FraudDetectionFlag` annotation and, if it's there, it starts the fraud detector. I will say it again: keep in mind that <u>**this method is invoked in the system before committing every database transaction**</u>, and, therefore, the code should try to check as few objects as possible and do it as fast as possible.  

```
@Component("jmixapp_ApplicationTransactionListener")  
public class ApplicationTransactionListener implements BeforeCommitTransactionListener {  
private static final Logger log = LoggerFactory.getLogger(ApplicationTransactionListener.class);  
private final FraudDetector fraudDetector;  
public ApplicationTransactionListener(FraudDetector fraudDetector) {  
    	this.fraudDetector = fraudDetector;  
}  
@Override  
public void beforeCommit(String storeName, Collection<Object> managedEntities) {  
    	for (Object e : managedEntities) {  
        	if (EntityValues.isEntity(e)  
                	&& !EntityValues.isSoftDeleted(e)  
                	&& e.getClass().isAnnotationPresent(FraudDetectionFlag.class)) {  
            	boolean ok = fraudDetector.feedAndFastCheck(e);  
            	if (!ok) {  
                	logFraudDetectionFailure(e);  
                	String msg = String.format(  
                        	"Fraud detection failure in '%s' object with id = '%s'",  
                        	e.getClass().getSimpleName(), EntityValues.getId(e)  
                	);  
                	throw new ValidationException(msg);  
            	}  
        	}  
    	}  
}  
private void logFraudDetectionFailure(Object e) {  
    	log.warn("Fraud detection failed for {}:{}", e.getClass().getSimpleName(), EntityValues.getId(e));  
}  
} 
```
To become a transaction listener, a manageable bean has to implement the `BeforeCommitTransactionListener` interface and the `beforeCommit` method. Transaction listeners are bound automatically at the application start-up. Jmix registers all classes that implement `BeforeCommitTransactionListener` or `AfterCompleteTransactionListener` as transaction listeners.   

## Conclusion  

Bean Validation (JSR 303, 349 and 380) is an approach that can serve as a reliable basis for 95% of the data validation cases encountered in an enterprise project. The main advantage of this approach is that most of the validation logic is concentrated inside the domain model classes. Therefore, it is easy to find, easy to read, and easy to maintain. Spring, Jmix, and many other frameworks support these standards and automatically carry out validations while receiving data at the UI layer, at the invocation of validated methods, or during the ORM data storage process.  

Some developers regard the domain model class level validation as unnatural and too complex, preferring UI-level data validation. However, using multiple validation points in the UI components and controllers is not the most rational approach. Validation methods mentioned in this article don't look unnatural when they are integrated into the platform, which contains bean validators and listeners and automatically integrates them with the client layer. 

Here are the rules for choosing the validation method:  
- **JPA validation** possesses limited functionality, but it is a good choice for the simplest validations inside the entity's classes when such constraints can be shown in DDL.  
- **Bean Validation** is a flexible, minimalistic, declarative, reusable, and readable way of setting up the majority of validations in the domain classes. In the majority of cases it is the best choice, unless you have to run validations inside transactions.   
- **Validation by contract** is bean validation, but for method invocations. Use it for input and output method parameters, e.g. in REST controllers.  
- **Entity listeners**: though they are not as declarative as Bean Validation annotations, they are perfectly suitable for validating large graphs or for validations inside database transactions, for example, when you have to read the data from the database to make a decision.   
- **Transaction listeners** are a powerful tool for working inside the transaction context. However, they require very careful treatment. Use it when you have to inspect various entity types using the same validation algorithm or when you have to decide which objects to validate in the course of execution.  

We hope that this article has helped you refresh your knowledge about various validation methods in enterprise Java applications. We also hope that it has given you some ideas for optimizing the architecture of your current projects.  

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Event-driven Approach to Development of Process Applications with Jmix BPM]]></title>
            <link>https://www.jmix.io/blog/event-driven-approach-to-development-of-process-applications-with-jmix-bpm</link>
            <guid>https://www.jmix.io/blog/event-driven-approach-to-development-of-process-applications-with-jmix-bpm</guid>
            <pubDate>Fri, 17 Oct 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Event_driven_Approach_1080h1920_without_date_825fe896b1.png">On this webinar, we showed you how to use Jmix BPM to build event-driven processes.]]></description>
            <content:encoded><![CDATA[Event-Driven Approach to Development of Process Applications

How do you turn a BPMN diagram from a static model into a real, event-driven application?
That was the focus of our latest Jmix webinar, where we explored how to make process automation reflect actual business events - not just documentation.

During the session, we showed how to:
- apply the event-oriented approach to business process automation in practice;
- choose and use the right BPMN tools;
- organize interprocess interaction in Jmix BPM.

If you’re new to BPMN or want to apply the event-driven approach in your own project, [contact us](https://www.jmix.io/contacts/) — we’ll be happy to walk you through the essentials and help you get started.

<iframe width="560" height="315" class="b-youtube-player" src="https://www.youtube.com/embed/REqb_POXrlc?si=F4-vee4FGk04k3MM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Create an Admin Interface Quickly]]></title>
            <link>https://www.jmix.io/blog/how-to-create-an-admin-interface-quickly</link>
            <guid>https://www.jmix.io/blog/how-to-create-an-admin-interface-quickly</guid>
            <pubDate>Tue, 16 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Admin_Panel_Blog_1200x630_dc779e6ed3.png">We would like to demonstrate how to solve typical problems while creating an admin interface in Jmix and to show the benefits and the limitations of this approach.  ]]></description>
            <content:encoded><![CDATA[We often hear at conferences and other events how different development teams struggle with the problem of having to develop an admin interface quickly and efficiently. Some of them go for expensive custom solutions they develop all by themselves; others try looking for ready-made alternatives on the market that would fit all their business requirements. Certain hybrids of the two approaches are not unheard of. The problems they thus solve might look familiar to our team members, since we have had to deal with them too. We are lucky though to have a tool that offers a natural solution to the problem, a tool we have built ourselves. So, in this article, we would like to demonstrate how to solve typical problems while creating an admin interface in Jmix and to show the benefits and the limitations of this approach.  

## Typical admin interface requirements  

First of all, we must determine the requirements that the admin interface should cover.  

- Data access in the database and the possibility to edit them. It is related to entity creation, DTO and CRUD screens. The entity number can be quite large, so the task of optimizing this process will be of a high priority. Apart from the data model and screen creation process optimization, you have to take into account the time spent writing migration scripts, mappers and other infrastructure elements, since these tasks are also resource intensive.  
- Differentiation of access rights. Role model creation is critically important, since an admin interface gives access to sensitive data and to system functions.    
- Audit. In this context, audit means tracking changes in the data model. It is necessary both for the support engineer work, to sort out a problematic situation, and for incident investigations and unauthorized action detection.  
- Granting access to functions and data for external services. Usually it means implementing various REST endpoints for CRUD actions with data and for interaction with internal services. When the number of entities is significant, the routine creation of CRUD endpoints can take a lot of time.  

## What is Jmix? 

### Framework architecture 

Jmix Framework is a full stack open-source framework for creating web applications, which is based on Spring Boot and Vaadin Flow. The main goal of the framework is to automate the routine actions for the developer, while preserving the development process flexibility and the easy access to the familiar tooling.  

A Jmix application is a Spring Boot application with a set of Jmix starters. You can also include any other starters you are familiar with. To work with data, Jmix uses a unified data model based on the EclipseLink ORM framework. 

The Vaadin Flow SSR web framework is responsible for working with the client side. It is based on the Web Components specification and the Google Polymer library suite. In Vaadin Flow, visual components consist of the client-side and the server-side parts.  The client-side component code is written in JavaScript and TypeScript, white the server-side components are written in Java. They communicate with each other via AJAX requests. Therefore, Jmix Framework used the same language to write both the backend and the frontend parts of the application.  

In order to work with Jmix Framework, a special Jmix Studio plugin suitable for IntelliJ IDEA, OpenIDE, and GigaIDE is used. Studio offers basic tools for working with the framework components, such as screens, roles, or entities.  

Note that Jmix doesn't position itself as a Low Code platform, since writing up the business logic is necessary for creating a fully-functional application, but certain Low Code elements are present in the form of various designers. In this case, a Less Code platform with auxiliary code generation components would be a more accurate definition.  

## How Jmix solves the admin interface problems  

### CRUD generation and visual designers

As we have already specified while discussing the requirements, the highest priority task of the admin interface creation process is the creation of a volumetric data model and the CRUD interfaces to work with it. 

For this purpose, Jmix Studio offers various visual designers to work with the most basic application components. One of those is the entity designer. In an entity designer, you can specify connections between entities, define attributes and set constraints for them. Visual designers just modify what is represented in the application source code. This code can also be modified manually without involving the visual designer. The alterations written into the code will be reflected in the designer and vice versa.  

```
@Entity 
@Table(name = "USER_", indexes = { 
        @Index(name = "IDX_USER__ON_USERNAME", columnList = "USERNAME", unique = true), 
        @Index(name = "IDX_USER__DEPARTMENT", columnList = "DEPARTMENT_ID") 
}) 
public class User implements JmixUserDetails, HasTimeZone { 
 
    @Id 
    @Column(name = "ID", nullable = false) 
    @JmixGeneratedValue 
    private UUID id; 
 
    @Version 
    @Column(name = "VERSION", nullable = false) 
    private Integer version; 
 
    @Column(name = "USERNAME", nullable = false) 
    private String username; 
 
    @Secret 
    @SystemLevel 
    @Column(name = "PASSWORD") 
    private String password; 
 
    @Column(name = "FIRST_NAME") 
    private String firstName; 
 
    @Column(name = "LAST_NAME") 
    private String lastName; 
 
    @Email 
    @Column(name = "EMAIL") 
    private String email; 
 
    @Column(name = "ACTIVE") 
    private Boolean active = true; 
 
    @Column(name = "TIME_ZONE_ID") 
    private String timeZoneId; 
 
    @Column(name = "ONBOARDING_STATUS") 
    private Integer onboardingStatus; 
 
    @JoinColumn(name = "DEPARTMENT_ID") 
    @ManyToOne(fetch = FetchType.LAZY) 
    private Department department; 
 
    @OrderBy("sortValue") 
    @Composition 
    @OneToMany(mappedBy = "user") 
    private List<UserStep> steps; 
 
    @Column(name = "JOINING_DATE") 
    private LocalDate joiningDate; 
 
    @Column(name = "PICTURE", length = 1024) 
    private FileRef picture; 
 
    @Transient 
    private Collection<? extends GrantedAuthority> authorities; 
     
    // getters & setters 

```

The designer offers us an opportunity to familiarize ourselves with the available settings for the entity and its attributes. The elements responsible for entity index handling are also here.  

When the data model is ready, we can start generating the CRUD screens. A special generator exists for this purpose, which can be called via a dialog window.  

This dialog window is a screen creation wizard, in which you can select thet generation template and fill it in with the necessary parameters. You don't have to use the template; it's okay to create a custom layout from scratch. There is a blank template for this purpose, which only contains the screen's skeleton.  

The View & Edit screen generator analyzes the entity's metamodel in order to create the necessary visual components for working with entities. Besides, for the View screen a table will be generated containing the selected columns corresponding to the entity attributes.  

For example, the following model represents a component generation example based on the entity attribute type information: 

<br>
<style type="text/css">
.tg  {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-bn4o{font-size:18px;font-weight:bold;text-align:center;vertical-align:top}
.tg .tg-13pz{font-size:18px;text-align:center;vertical-align:top}
</style>
<table class="tg" style="undefined;table-layout: fixed; width: 483px"><colgroup>
<col style="width: 144px">
<col style="width: 128px">
<col style="width: 211px">
</colgroup>
<thead>
  <tr>
    <th class="tg-bn4o">Attribute<span style="color:#000"> </span></th>
    <th class="tg-bn4o">Type<span style="color:#000"> </span></th>
    <th class="tg-bn4o">Component to edit <span style="color:#000"> </span></th>
  </tr></thead>
<tbody>
  <tr>
    <td class="tg-13pz">username<span style="color:#000"> </span></td>
    <td class="tg-13pz">String<span style="color:#000"> </span></td>
    <td class="tg-13pz">TextField<span style="color:#000"> </span></td>
  </tr>
  <tr>
    <td class="tg-13pz">password<span style="color:#000"> </span></td>
    <td class="tg-13pz">String<span style="color:#000"> </span></td>
    <td class="tg-13pz">PasswordField<span style="color:#000"> </span></td>
  </tr>
  <tr>
    <td class="tg-13pz">email<span style="color:#000"> </span></td>
    <td class="tg-13pz">String<span style="color:#000"> </span></td>
    <td class="tg-13pz">EmailField<span style="color:#000"> </span></td>
  </tr>
  <tr>
    <td class="tg-13pz">active<span style="color:#000"> </span></td>
    <td class="tg-13pz">Boolean<span style="color:#000"> </span></td>
    <td class="tg-13pz">Checkbox<span style="color:#000"> </span></td>
  </tr>
</tbody></table>
<br>

The generated components will be bound with the data. If you edit a component via its bound attribute and then click the Save button, a commit to the database will take place.  

The screens that have been created can be modernized, and their own business logic can be implemented inside them.  

If you need not just the data from the SQL-based database, there is an option to create a DTO for the entity and then work with it in the same way you work with the JPA entities themselves. However, it will be necessary to configure a service, which is going to receive this data from an external source. If you don't feel like configuring something, you can put the OpenAPI's generator schema into Studio to generate the data model and the client.  

Talking about generators, AI assistants are used more and more often, for example, for UI, REST interface, or entity structure generation. It saves a lot of time, but such an approach to generation might not take into account the project specifics or business context. You have to be careful and work according to the "trust but check" principle. If you don't thoroughly proofread your generated code, you can get serious problems with its maintenance.  

This is why Jmix emphasizes generators. But if the task still remains a routine one, while outside of the generators' scope, you can use the built-in AI Assistant panel in Jmix Studio. Pre-trained for specifics, the Jmix model understands the context and is capable of generating more complex code. But the same rule about checking the resulting code still applies, since any AI model can hallucinate.  

### Role model 

Jmix has a built-in control system for access, based on Spring Security. A role is the central component of this system. There are two types of roles in the framework: resource roles and row-level roles.  

- Resource roles are used to grant the user access to a resource. It can be an entity, a service API, or screens. By default, a new user has no access to anything.  
- Row-level roles are used to forbid a user access to those table rows, for which he or she already has resource-level access. It can be useful for such cases as, for example, a manager who should have access to viewing employees from the same department only.  

Thanks to the full stack architecture, we can set it up so that the role model will cover every layer of the application, from the data model to the user interface.  

This way, a role, once created, will control all access to the system's functions. For example, while loading entities from the API to let them interact with the database, filtered results will be removed or an access error thrown. If a visual component is related to some data, the limitations associated with the current role will be applied to this visual component, as well. If the user has only viewing rights, the input field will be seen as read-only. If the user has no rights even to view this information, the visual component won't be displayed on the screen at all.  

There are two ways of creating a role: a programmatic and a manual one. When the role is created programmatically, the developer creates a special Java interface that describes access rights for the role. Jmix Studio contains special designers that receive information about the application's architecture and make it possible to choose the necessary rights for various parts of the application via the interface. 
 
```
import com.company.onboarding.entity.Step; 
import com.company.onboarding.entity.User; 
import com.company.onboarding.entity.UserStep; 
import io.jmix.security.model.EntityAttributePolicyAction; 
import io.jmix.security.model.EntityPolicyAction; 
import io.jmix.security.role.annotation.EntityAttributePolicy; 
import io.jmix.security.role.annotation.EntityPolicy; 
import io.jmix.security.role.annotation.ResourceRole; 
import io.jmix.securityflowui.role.annotation.MenuPolicy; 
import io.jmix.securityflowui.role.annotation.ViewPolicy; 
 
@ResourceRole(name = "Employee", code = "employee", scope = "UI") 
public interface EmployeeRole { 
    @MenuPolicy(menuIds = "MyOnboardingView") 
    @ViewPolicy(viewIds = "MyOnboardingView") 
    void screens(); 
 
    @EntityAttributePolicy(entityClass = User.class, 
            attributes = "*", 
            action = EntityAttributePolicyAction.VIEW) 
    @EntityPolicy(entityClass = User.class, 
            actions = {EntityPolicyAction.READ, EntityPolicyAction.UPDATE}) 
    void user(); 
 
    @EntityAttributePolicy(entityClass = UserStep.class, 
            attributes = "*", 
            action = EntityAttributePolicyAction.VIEW) 
    @EntityPolicy(entityClass = UserStep.class, 
            actions = {EntityPolicyAction.READ, EntityPolicyAction.UPDATE}) 
    void userStep(); 
 
    @EntityAttributePolicy(entityClass = Step.class, 
            attributes = "*", 
            action = EntityAttributePolicyAction.VIEW) 
    @EntityPolicy(entityClass = Step.class, 
            actions = EntityPolicyAction.READ) 
    void step(); 
} 
```
Apart from this, if the system works on the production server, the administrator can create the necessary role and assign a user to it without contacting the developer. Such roles will be stored in the database and have the same priority as the roles created at the development stage.  

### Audit 

To close the audit tasks, the framework has a special Audit add-on. This add-on, like many others, is accessible through the add-on marketplace in Jmix Studio. 

When you install the add-on into the application, a special Spring Boot starter is added. Add-ons can have purely service functionality, or they can contain additional interface elements, including new components and system screens.  

Audit add-on brings with it screens for audit rule creation. For example, all attributes of the User entity get audited.  

The screen next to it contains audit records, which can be used for change tracking.  

We have decided to place this information directly into the UI, so that the system users could be granted access to it, and not just the programmers.

### Working with the UI 

The main element of the user interface in Jmix are the screens. The screens are UI components from Vaadin Flow. They have two main elements: the Java controller and the XML layout.  

The XML layout is optional and is used for the component declarative description and their placement on the screen. The Java controller is the main screen element that describes the business logic connected with the UI. That is where you process the data, change component states throughout the screen lifecycle, or create event handlers for various events.  

Using XML layout, you can compose the screen template, add all the necessary visual components and connect them with the data. For each component, there is an inspector that shows the properties that can be modified, and the list of hooks, which can be implemented.  

To avoid having to restart the application each time you change something in the UI, the hot-deploy feature exists. With its help, you can modify the screen, its business logic and just save the file. The saving action will trigger the loading of all modifications into the running application.  

### Automated data migration

While updating the data model, the problem of synchronizing the changes with the database always arises. Jmix Studio has a migration mechanism for this, which is based on Liquibase. Each time the model is modified, a changelog is generated and applied to the database. Each add-on that carries with it a set of system entities, also has its own pre-prepared set of changelogs.  

Besides, if the development is done "from the database", a built-in reverse engineering system exists, which can generate the data model from the database tables.

## Comparison with other options and limitations

The first notable difference is the presence of ready-made architecture. Jmix uses project templates. From the moment you start the IDE to the moment you run the project only a few minutes pass. In the case when you have to create several similar admin panels it can save you a lot of time. Naturally, this approach has its drawbacks. If a standard application template doesn't match your needs, you will have to create your own template, and that means more time spent.  

When you are using native technologies, there is no such problem, since the project is flexibly configured. However, such a configuration can require a few days of work.  

The second difference is the fact that the framework offers a higher level of abstraction. Existing APIs that provide database interactions, declarative configuring os UI components and visual configuration for the security model lower the entry threshold for developers for using the necessary technologies. These approaches do not forbid manual configuring and fine-tuning for the necessary systems. Moreover, if something in the framework works differently from the programmer's wishes, there is always a possibility to override the necessary behavior. We, as the framework creators, always do our best to leave extension points and override points for the majority of systems and modules, which makes it easier to change the framework behavior to match your needs.  

Moving forward to the comparison with technologies the framework is based on, a logical question arises: why not use these technologies as they are and what is the framework for? The main points are described in the table below.  

<br>
<style type="text/css">
.tg  {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-bn4o{font-size:18px;font-weight:bold;text-align:center;vertical-align:top}
.tg .tg-nx8p{font-size:18px;text-align:left;vertical-align:top}
</style>
<table class="tg"><thead>
  <tr>
    <th class="tg-bn4o">Characteristic<span style="color:#000"> </span></th>
    <th class="tg-bn4o">Spring Boot + Vaadin Flow<span style="color:#000"> </span></th>
    <th class="tg-bn4o">Jmix<span style="color:#000"> </span></th>
  </tr></thead>
<tbody>
  <tr>
    <td class="tg-nx8p">Architecture<span style="color:#000"> </span></td>
    <td class="tg-nx8p">Flexible<span style="color:#000"> </span></td>
    <td class="tg-nx8p">Monolith with multi-modularity support <span style="color:#000"> </span></td>
  </tr>
  <tr>
    <td class="tg-nx8p">UI<span style="color:#000"> </span></td>
    <td class="tg-nx8p">Ready component palette, manual layout work and manual data binding <span style="color:#000"> </span></td>
    <td class="tg-nx8p">Ready component palette + data binding + module stubs. <span style="color:#000"> </span></td>
  </tr>
  <tr>
    <td class="tg-nx8p">Security system<span style="color:#000"> </span></td>
    <td class="tg-nx8p">Self-developed, flexible<span style="color:#000"> </span></td>
    <td class="tg-nx8p">Ready out of the box, end-to-end within the project <span style="color:#000"> </span></td>
  </tr>
  <tr>
    <td class="tg-nx8p">Data sources <span style="color:#000"> </span></td>
    <td class="tg-nx8p">Any, manual setup <span style="color:#000"> </span></td>
    <td class="tg-nx8p">Any SQL-based + model generation and OpenAPI client generation<span style="color:#000"> </span></td>
  </tr>
  <tr>
    <td class="tg-nx8p">Development speed<span style="color:#000"> </span></td>
    <td class="tg-nx8p">Average, typical tasks solved manually <span style="color:#000"> </span></td>
    <td class="tg-nx8p">Very high at the start, high later <span style="color:#000"> </span></td>
  </tr>
  <tr>
    <td class="tg-nx8p">Support costs<span style="color:#000"> </span></td>
    <td class="tg-nx8p">High, depend on architecture solutions <span style="color:#000"> </span></td>
    <td class="tg-nx8p">Low<span style="color:#000"> </span></td>
  </tr>
  <tr>
    <td class="tg-nx8p">Solution flexibility<span style="color:#000"> </span></td>
    <td class="tg-nx8p">Very high, you can do everything… or almost everything:)<span style="color:#000"> </span></td>
    <td class="tg-nx8p">Average, customization possible within the Jmix and Vaadin architecture<span style="color:#000"> </span></td>
  </tr>
</tbody></table>
<br>

If you use Jmix, you can get a large amount of ready-made functionality. However, as a trade-off, you have to accept the rules and restrictions pertaining to its architecture. 

We all know that Server-side UI requires additional resources from the server. It happens because when we create a session at the server side, a full-scale UI instance is also created. In case of Jmix, we need to allocate approximately 10 Mb of memory per session. Besides, this approach imposes limitations on the interface customization capabilities, unlike when working with React + AntDesign. 

Not all the familiar Java technologies are supported by the framework. For example, if you have to use non-relational databases, you will have to describe the DataStore on your own. Besides, using the not-so-mainstream EclipseLink framework under the hood can scare someone away.  

What's more, Jmix definitely won't be the best option, of you use the microservice architecture. The reason for it is that because of the server-side UI approach user sessions consume a lot of memory. Consequently, it is very difficult to serialize the entire session. Therefore, the only option for load balancing is to use sticky sessions. 

## Summary

On the whole, if you use only the functionality described above, you can create a good admin panel. Many of the problems well known to every developer are solved at the framework level. The framework contains a ready-made UI for CRUD development: forms, tables, and filters. A suite of add-ons solves typical problems such as audit setup, full-text search integration, or live notification system.   

However, you shouldn't think that the framework is a kind of silver bullet for solving your business tasks. It has a number of limitations, which should be taken into account while analyzing the applicability of the tool. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deploy Jmix apps to Kubernetes]]></title>
            <link>https://www.jmix.io/blog/deploy-jmix-apps-to-kubernetes</link>
            <guid>https://www.jmix.io/blog/deploy-jmix-apps-to-kubernetes</guid>
            <pubDate>Tue, 09 Sep 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Deploy_Jmix_to_Kubernetes_02_50d9b981ef.png">The Kubernetes clustering software is becoming server applications management standard as, probably, the most feature rich and widely supported infrastructure toolchain.]]></description>
            <content:encoded><![CDATA[The Kubernetes clustering software is becoming server applications management standard as, probably, the most feature rich and widely supported infrastructure toolchain. However, it is still hard to set up from scratch. This can be fine when you run on cloud hosting with unlimited capacity but causes problems when you have to use your own software, or a custom configuration is needed. The good news is that such problems don’t usually appear at the application level, so you should be able to easily change your cluster software vendor when required without rewriting your applications from scratch. 

To run our own K8s cluster, we will use MicroK8s as a quite lightweight and easy to use but powerful distribution. It is developed by Canonical (a Ubuntu Linux OS vendor) but still available for various Linux distributions as well as Windows and MacOS X operating systems using virtualization technologies. System-on-a-Chip devices like RaspberryPi and clones are also capable of running MicroK8s cluster nodes.  

The set of extensions will allow you to manage your server software including  LLM-model servers and agents. 

In comparison to Minikube, another popular Kubernetes mini distribution, MicroK8s, enables clustering features and brings further helpful addons, making it a good choice for Small Office or Home infrastructures as well as for IT technology enthusiasts. 

We are going to build a Jmix framework application and deploy it to a  Kubernetes cluster configured by ourselves.  

To start playing, we will need a virtual or dedicated server with at least 3-4 Gb RAM. You can rent a server with a hosting provider or even use your own PC or device. 

When you obtain a server, you usually should have SSH access details for it that consist of an IP address, login and password information. 

First, we will setup SSH-key authentication on it to login smoothly. 

For Windows, you can use GitBash console or MSYS toolchain or PuTTY or setup WSL software to connect to your server. 

## Set up your server connection 

Generate your identity SSH-key if you haven't done this before 

```
ssh-keygen -t ed25519
``` 

Assume your server’s IP address is `45.87.104.148` 

Install your SSH-key with a `ssh-copy-id` command 

```
ssh-copy-id root@45.87.104.148
```

After that, you be able to connect to server without a password  

```
ssh root@45.87.104.148
``` 

It is quite useful to have terminal sessions management software like Screen, Byobu or tmux that will keep your terminal session open after you have closed the terminal window. 

## Install MicroK8S 

Create and configure non-privileged user. 

```
useradd kubeuser
usermod -aG sudo,microk8s kubeuser
```

Set password for this user or copy your public SSH key to this user’s `/home/kubeuser/.ssh/authorized_keys` file. 

If your distribution doesn’t have Snap package manager, you will have to install it first 

```
sudo apt install snapd
```

On Debian, I also had to install snap core package with 

```
sudo snap install core
```

Then you will be able to install MicroK8s packages: 

```
sudo snap install microk8s --classic
```
Relogin to SSH with newly created kubeuser. 

Official docs also advise to configure a firewall in case you are using Ubuntu; this can be done with the following CLI execution: 

```
sudo ufw allow in on cni0 && sudo ufw allow out on cni0
sudo ufw default allow routed
```

Install some “must-have” addons: 

```
microk8s enable dns
microk8s enable dashboard
microk8s enable storage
microk8s enable host-access
```

## Install the kubectl tool 

To manage your microk8s you can use the `microk8s kubectl` command tool but it is also possible to install the original kubectl tool. This will be helpful in case your cluster is hosted on a separate server or a number of them. To do that run:  

```
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
cp kubectl /usr/local/bin
```

This will download the binary build for Linux and copy it into the `Path` folder.  

Import context configuration from cluster to the current user’s kubectl profile   

```
microk8s config > $HOME/.kube/config
```

If you plan to build the project on a local PC, copy this configuration relative to your local home folder. 

After that you will be able to use the `kubectl` command instead of microk8s kubectl. 

## Set up web panel 

It can be quite useful to operate from a fancy looking web interface. You can enable it on a temporary basis, which seems more secure, by running the `dashboard-proxy` command: 

```
microk8s dashboard-proxy
```

You will see the port number and the access token in the command output 

![]({{strapiUrl}}/uploads/1_a06e7b2096.png)

Or on permanent basis by applying the following resource: 

dashboard.json - [https://pastebin.com/RRg8z5t0](https://pastebin.com/RRg8z5t0)
```
{ 
  "apiVersion": "v1", 
  "kind": "Service", 
  "metadata": { 
    "labels": { 
      "k8s-app": "kubernetes-dashboard" 
    }, 
    "name": "kubernetes-dashboard-np", 
    "namespace": "kube-system" 
  }, 
  "spec": { 
    "type": "NodePort", 
    "ports": [ 
      { 
        "port": 443, 
        "protocol": "TCP", 
        "targetPort": 8443, 
        "nodePort": 30000 
      } 
    ], 
    "selector": { 
      "k8s-app": "kubernetes-dashboard" 
    } 
  } 
} 
```

Use your server’s external IP address and the given port to open the dashboard in the browser. 

After you have opened the dashboard, it will ask to authenticate with a token.  

You can obtain it from the server’s terminal by running the following commands: 

```
token=$(microk8s kubectl -n kube-system get secret | grep default-token | cut -d " " -f1) && microk8s kubectl -n kube-system describe secret $token | grep token:
```

## Container image registry 

A wide number of services like GitHub or Gitlab nowadays are allowing free container images hosting services as an alternative to DockerHub.   

To use the docker image registry provided by GitHub, you must create an access token first. 

Go to Settings -> Developer Settings of your account and open the Personal Access Tokens -> Tokens(class) section. 

Generate a new token with the `write:packages` permission. 

Save the generated token value: you will use it instead of the account password in configurations. 

## Jmix project setup 

Install git if you haven’t done this before 

```
sudo apt install git
git clone https://github.com/jmix-framework/jmix-onboarding-2.git
```

When the application will be deployed the key parameter vales will be provided by the cluster configuration. So you need to choose one from the following two options: 

1. Setup application.properties configuration with variables
  As the minimum requirement you will need to set up the datasource configuration as follows: 
  ```
  main.datasource.url = jdbc:postgresql://${DB_HOST}:5432/${DB_NAME}?stringtype=unspecified main.datasource.username = ${DB_USER} main.datasource.password =${DB_PASSWORD}
  ```
2. Enable profile-based configuration  

Create the `application-dev.properties`, `application-prod.properties` files  

Move the datasource configuration with hardcoded HSQL values to `application-dev.properties` 

Create a “variable”-rich version of datasource confirugration in `application-prod.properties` as in p. 1 

Add also a Hazelcast JCache configuration: 

```
spring.cache.jcache.provider = com.hazelcast.cache.HazelcastMemberCachingProvider
```

Add PostgreSQL and Hazelcast drivers to build.gradle’s dependencies section 

```
implementation 'org.postgresql:postgresql'
implementation 'com.hazelcast:hazelcast'
```

Add profile activation to `build.gradle` 

```
bootRun { 
    args = ["--spring.profiles.active=dev"] 
} 
tasks.named("bootBuildImage") { 
    environment["BPE_APPEND_JAVA_TOOL_OPTIONS"] = " -Dspring.profiles.active=prod" 
}
```

To use our custom container image registry, also add the IP/port  

```
bootBuildImage { 
  docker { 
  publishRegistry { 
    url = 'https://ghcr.io/GITHUB_LOGIN/sample-spp' 
 username = 'GITHUB_LOGIN' 
 password = 'GITHUB_TOKEN'   
  } 
} 
```
 

Replace `GITHUB_LOGIN` and `GITHUB_TOKEN` with your account’s real values in the above and the further examples. 

Install Java on the computer where you are going to build your application from sources. 

```
sudo apt install openjdk-21-jdk
```

To build  an application container image, run the following Gradle command: 
```
./gradlew -Pvaadin.productionMode=true bootBuildImage --imageName=ghcr.io/GITHUB_LOGIN/sample-app --publishImage 
```

You should see successful status messages after a bit of time elapses during the building process: 

![]({{strapiUrl}}/uploads/2_4cc23e5416.png) 

## Delivery 

To use GitHub’s Docker registry, you need to add a secret to the cluster 

```
kubectl create secret docker-registry registrysecret --docker-server=ghcr.io --docker-username=GITHUB_LOGIN--docker-password=GITHUB_TOKEN 
```
 

Create a `k8s/` folder in a location you are comfortable with. It can be the `project` folder, but professionals prefer to keep deployment configurations separated from sources.  

Add the files listed below to the folder. 

## Database Service Configuration 

This file defines the PostgreSQL database service named `sample-db-service`. 

k8s/db.json - [https://pastebin.com/Ay0uB3Ra](https://pastebin.com/Ay0uB3Ra) 

```
{ 
  "apiVersion": "v1", 
  "kind": "ConfigMap", 
  "metadata": { 
    "name": "sample-db-config" 
  }, 
  "data": { 
    "db_name": "sample", 
    "db_user": "root", 
    "db_password": "root", 
    "db_port": "5432" 
  } 
} 
```
 

k8s/db-persistance.json - [https://pastebin.com/pQq4QvUF](https://pastebin.com/pQq4QvUF)

```
{ 
  "apiVersion": "v1", 
  "kind": "PersistentVolumeClaim", 
  "metadata": { 
    "name": "sample-db-pvclaim" 
  }, 
  "spec": { 
    "accessModes": [ 
      "ReadWriteOnce" 
    ], 
    "resources": { 
      "requests": { 
        "storage": "5Gi" 
      } 
    } 
  } 
} 
```

k8s/db-deployment.json - [https://pastebin.com/xKF1hKwT](https://pastebin.com/xKF1hKwT)

```
{ 
  "apiVersion": "apps/v1", 
  "kind": "Deployment", 
  "metadata": { 
    "name": "sample-db" 
  }, 
  "spec": { 
    "replicas": 1, 
    "selector": { 
      "matchLabels": { 
        "app": "sample-db" 
      } 
    }, 
    "strategy": {}, 
    "template": { 
      "metadata": { 
        "labels": { 
          "app": "sample-db" 
        } 
      }, 
      "spec": { 
        "volumes": [ 
          { 
            "name": "sample-db-storage", 
            "persistentVolumeClaim": { 
              "claimName": "sample-db-pvclaim" 
            } 
          } 
        ], 
        "containers": [ 
          { 
            "image": "postgres", 
            "name": "sample-db", 
            "env": [ 
              { 
                "name": "POSTGRES_USER", 
                "valueFrom": { 
                  "configMapKeyRef": { 
                    "name": "sample-db-config", 
                    "key": "db_user" 
                  } 
                } 
              }, 
              { 
                "name": "POSTGRES_PASSWORD", 
                "valueFrom": { 
                  "configMapKeyRef": { 
                    "name": "sample-db-config", 
                    "key": "db_password" 
                  } 
                } 
              }, 
              { 
                "name": "PGDATA", 
                "value": "/var/lib/postgresql/data/pgdata" 
              }, 
              { 
                "name": "POSTGRES_DB", 
                "value": "sample" 
              } 
            ], 
            "ports": [ 
              { 
                "containerPort": 5432, 
                "name": "sample-db" 
              } 
            ], 
            "volumeMounts": [ 
              { 
                "name": "sample-db-storage", 
                "mountPath": "/var/lib/postgresql/data" 
              } 
            ] 
          } 
        ] 
      } 
    } 
  } 
} 
``` 

k8s/db-service.json - [https://pastebin.com/mwkLfNx1](https://pastebin.com/mwkLfNx1) 

```
{ 
  "apiVersion": "v1", 
  "kind": "Service", 
  "metadata": { 
    "name": "sample-db-service" 
  }, 
  "spec": { 
    "type": "NodePort", 
    "ports": [ 
      { 
        "port": 5432, 
        "name": "sample-db-db" 
      } 
    ], 
    "selector": { 
      "app": "sample-db" 
    } 
  } 
} 
```

## Application Service Configuration 

The following  file defines the application service named `sample-app-service`. It uses the `sample-registry/sample-app` Docker image with our application. 

k8s/app.json - [https://pastebin.com/4j8vYekg](https://pastebin.com/4j8vYekg) 

```
{ 
  "apiVersion": "apps/v1", 
  "kind": "Deployment", 
  "metadata": { 
    "name": "sample-app" 
  }, 
  "spec": { 
    "replicas": 1, 
    "selector": { 
      "matchLabels": { 
        "app": "sample-app" 
      } 
    }, 
    "template": { 
      "metadata": { 
        "labels": { 
          "app": "sample-app" 
        } 
      }, 
      "spec": { 
    "imagePullSecrets": [ 
      {"name": "registrysecret"} 
    ],       
        "containers": [ 
          { 
            "image": "ghcr.io/syncro/sample-app:latest", 
            "imagePullPolicy": "Always", 
            "name": "sample-app", 
            "env": [ 
              { 
                "name": "DB_NAME", 
                "valueFrom": { 
                  "configMapKeyRef": { 
                    "name": "sample-db-config", 
                    "key": "db_name" 
                  } 
                } 
              }, 
              { 
                "name": "DB_USER", 
                "valueFrom": { 
                  "configMapKeyRef": { 
                    "name": "sample-db-config", 
                    "key": "db_user" 
                  } 
                } 
              }, 
              { 
                "name": "DB_PASSWORD", 
                "valueFrom": { 
                  "configMapKeyRef": { 
                    "name": "sample-db-config", 
                    "key": "db_password" 
                  } 
                } 
              }, 
              { 
                "name": "DB_HOST", 
                "value": "sample-db-service" 
              }, 
              { 
                "name": "DB_PORT", 
                "valueFrom": { 
                  "configMapKeyRef": { 
                    "name": "sample-db-config", 
                    "key": "db_port" 
                  } 
                } 
              }, 
              { 
                "name": "SPRING_PROFILES_ACTIVE", 
                "value": "k8s" 
              } 
            ], 
            "lifecycle": { 
              "preStop": { 
                "exec": { 
                  "command": ["sh", "-c", "sleep 10"] 
                } 
              } 
            }, 
            "ports": [ 
              { 
                "containerPort": 8080 
              }, 
              { 
                "containerPort": 5701 
              } 
            ] 
          } 
        ] 
      } 
    } 
  } 
}
```

And the corresponding service assigning ports to container pods. 

k8s/app-service.json - [https://pastebin.com/ckBTVenH](https://pastebin.com/ckBTVenH) 

```
{ 
  "apiVersion": "v1", 
  "kind": "Service", 
  "metadata": { 
    "name": "sample-app-service" 
  }, 
  "spec": { 
    "type": "NodePort", 
    "ports": [ 
      { 
        "port": 8080, 
        "name": "sample-app-app" 
      }, 
      { 
        "port": 5701, 
        "name": "sample-app-hazelcast" 
      } 
    ], 
    "selector": { 
      "app": "sample-app" 
    } 
  } 
} 
```

## Run deployment configurations 

When we have all resource files in the folder, we can run them all with just one apply command: 

```
kubectl apply –f k8s/  
```

After that you can open the web panel and make sure that all status graphs are green; otherwise, you can check Logs from the Pos section. 

![]({{strapiUrl}}/uploads/3_305a869b25.png)

The typical problem in this case is the order of services starting. You can try to restart or reapply the application container if it hasn’t found the database as it was not yet started. 

To remove resources, use the same command but with the delete action 

```
kubectl delete –f k8s/ 
```

Then fix your configurations and try again 

## Check the results 

To know the port number assigned to the application run the kubectl command with result filtering: 

```
kubectl get all --all-namespaces | grep service/sample-app-service 
```

![]({{strapiUrl}}/uploads/4_e3d5a06a30.png) 
 

In my case, the port number was 30377, so the URL to open in my browser http://45.87.104.148:30377 

![]({{strapiUrl}}/uploads/5_da885fac2c.png)  

Check out the port that was mapped from 8080 and open it in browser. 

Consider enabling ingress services and cert-manager or an external proxy server like nginx or Traefik for real-life application deployments. 

## Enable clustering

Adding nodes to your cluster is quite easy, just execute 

```
microk8s add-node 
```

on the master node, and its output will contain the commands to run on another node, so it is joined to the cluster. This node must have MicroK8s installed, but Operating System distributions are not required to be the same.    

![]({{strapiUrl}}/uploads/6_69839f34d9.png) 

After running it you can check the state with  

```
kubectl get nodes  
```

Command or in Cluster -> Nodes section of Web Panel  

Now you can scale your application container to both running nodes. 

```
kubectl scale -n default deployment sample-app --replicas=2 
```

And check the result in Pods or Deployment sections. 

## Conclusion 

As you can see, MicroK8S enables  easy setup of Java/Jmix web application deployments for development, testing or SOHO purposes. This can be done in an extensible architecture way using your own hosted hardware resources or dedicated/virtual servers. The described approach keeps your software less vendor-locked, as you will be able to use the same source code, tools and resource configurations with other Kubernetes-compatible cluster software vendors and IT specialists.   ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Non-Blocking Call of an External Service Inside a Process]]></title>
            <link>https://www.jmix.io/blog/a-non-blocking-call-of-an-external-service-inside-a-process</link>
            <guid>https://www.jmix.io/blog/a-non-blocking-call-of-an-external-service-inside-a-process</guid>
            <pubDate>Wed, 27 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/N_agoj_Gl_I_G_G_i_b_a_G_b_16e1a74579.png">A helpful guide for those working with Camunda or Flowable who want to design processes the right way without surprises.]]></description>
            <content:encoded><![CDATA[Quite often one has to make API calls to various external services. In essence, it is a standard system orchestration scenario or even a microservice orchestration scenario (sorry for a buzzword). It looks simple and logical on a BPMN diagram – we knock at some door using an API, receive a response, and move on to the next task. For the analysis level models it is all quite normal.  

![undefined.png]({{strapiUrl}}/uploads/undefined_73f453927e.png)

## Synchronous and asynchronous running  

BPM engines support two types of task running: synchronous and asynchronous. In my opinion, those names are rather unfortunate and unfitting, and only add to confusion.

In fact, it is all about the transaction boundaries and not the real asynchrony. In the context of BPMN, asynchronous running of the tasks is related to how the process stores its state and handles the step execution.

When you mark a task as asynchronous (e.g., with `asyncBefore` in Camunda, or `async` in Flowable), the process execution is explicitly split into separate transactions. At the async boundary, the engine persists the current state of the process in the database and creates a job in the job queue. The special component later picks up that job and continues execution in a **new transaction**. (In Camunda, `asyncAfter` slightly differs — it means the split happens after the task executes but before the next step.) 

Therefore, asynchrony in BPMN is a way of handling transactions or task processing via a queue and not parallel execution of code or threads.  

## Synchronous tasks  

Service tasks are created as synchronous by default. There is certain logic in that: the engine works faster this way, since there is no need to store the process state in the database after every task. Everything is executed within the same transaction until we encounter a user task or another element that causes a waiting state. For simple tasks, which, for example, change the state of the process variable, carry out trivial calculations or write something into the log, this works fine. But in those cases when the result is not guaranteed and a failure is highly probable, synchronous running is exceedingly undesirable. Because it will cause a transaction rollback, the result of all previous tasks will be cancelled, and the process will throw an error. Do you really need any of it?  

![undefined.jpeg]({{strapiUrl}}/uploads/undefined_895e32a928.jpeg)

In general, if there is even a little potential risk that a certain task may fail to complete because of some external conditions, don't leave it synchronous by default. The asynchronous option is not a silver bullet either, but we are going to discuss that below. It is better than nothing, anyway.  

## Asynchronous tasks and Fail Retry 

Now, let's look at asynchronous tasks. As you have already realized asynchrony in BPMN doesn't imply independent execution. The token won't move forward until the task is completed. The only difference is this: now it is not the BPM engine that is responsible for the task execution, but a special component called the Job Executor. That is to say, all asynchronous tasks from all processes are lumped together in a common queue, and this very Job Executor executes them according to the queue order. If the task is completed successfully, the Job Executor informs the process about it, and the token moves forward. 

Meaning that we have artificially created a new transaction boundary, and now the result of the previous tasks won't be cancelled if something goes wrong: 

![undefined (1).jpeg]({{strapiUrl}}/uploads/undefined_1_82f318e1d1.jpeg)

Okay, and what is going to happen if our task is timed out or has thrown an exception? In BPMN terms it will be called a "technical error", and if the `fail retry` parameter is set, the `Job Executor` will attempt to execute it again and again until the `fail retry` counter is down to zero. Once it happens, Camunda will create an incident, and Flowable will just mark this task as `failed`. Then the admin can try to correct the situation manually somehow.  

It is a rather primitive solution, but it was invented twenty years ago, and in those days, it was considered the norm. Nobody hurried anywhere, the majority of processes involved some human actions, and human beings tend to slow the processes down. Therefore the recommended value for the `fail retry` parameter in Camunda and Flowable is still `R3/PT5M`, which means repeat three times in five minutes. For the completely automated processes adjusted for microservice orchestration, the five minute long pause between attempts looks like eternity. When we are in a fight for efficiency, it's usually the matter of milliseconds, and now this…  

And why can't we set the `fail retry`, for example, to a hundred times in a hundred milliseconds? Well, it won't work. This mechanism works like a `timer event`. That is, there is a special record in the database, and the already familiar `Job Executor` checks from time to time whether this timer is ready to click or not. From our practical experience, the minimum time for this is about 20 seconds, and less than that just doesn't work. Of course, it depends on the hardware, but it is never fast enough.  

But speed is not even the main consideration. Let's look at it from the logical point of view. We have a service that doesn't respond. And the system creates an instance of a process every second, and they keep trying to call the service in question. Or a hundred instances. Or a thousand. Before long you will find yourself overcrowded with processes knocking at the door of an unresponsive service. Fail retry cannot resolve such a situation by design. It can only exacerbate it.  

Which means that the time has come to accept the fact that this mechanism is outdated. It shouldn't be used for the solutions involved in completely automated processes with high intensity. So, what to do? You could look at the `Circuit Breaker` pattern, but that's a completely different story for another article.  

## Attached (boundary) events 

BPMN contains another mechanism, which can be leveraged for our scenario with an unreliable external service. We are talking about attached (a.k.a boundary) events. They can help us implement the scenario, just as we used to do it with fail retry, but in a more flexible way. For example, you can go into a repeated attempt via timeout, just the same as before, or you can escalate the task to an employee for manual completion.  

Suppose your process calls a certain service automatically, it is a counterparty checking service, and the API has been changed at the other side, so everything fails. Instead of creating incidents, the task can be delegated to a human being, who can simply phone your business partner. With error handling, the guiding principle is basically the same. If the service is returning some suspicious code, we can model any logic to react to it. It is a much more flexible approach than using fail retry, and a more visually comprehensible one, as well. The diagram becomes more complex, though. But life is a complex thing overall.  

![undefined (1).png]({{strapiUrl}}/uploads/undefined_1_4d491b32d5.png)

However, the service call in this implementation is still of the blocking type: the process is waiting for the task to complete. And an open transaction is left hanging.  

–  What will happen if the server fails while the transaction is still open?  

Nothing entirely fatal is going to happen. The transaction will be rolled back, since the engine uses a two-phase commit, and this behaviour is normal. However, if the transaction was not persisted, the BPM engine system will discover an incomplete task in the `ACT_RU_JOB` table at the restart and will process it again. That is, the task will be executed a second time. And if it is not idempotent, this can cause duplication of data. This is true for both the synchronous and the asynchronous mode.  

As you can see, long transactions in BPMN can create problems, even if they include only one task. Long transactions keep database-related resources and other system resources blocked, which can cause deadlocks and reduce the system's performance. And let's remember that there can be a lot of instances of that process. To summarize, long transactions are evil. So we would like not to leave the task hanging for an indefinite period of time, but to send a request to an external service, complete the task, move forward with the process, and then, later, receive the response.  

## Event-based gateway 

`Event-based gateway` is an element of BPMN used for making decisions based on events. Unlike other gateways, such as exclusive gateway, which make decisions based on data, event-based gateway waits for one of the several possible events and chooses a path inside a process depending on which event took place first.  

It looks like something useful and particularly fitting our scenario – we send a request to an unreliable service, add this magical gateway and then receive all versions of the response. Such a diagram is very easy to read; it clearly demonstrates all the possible results of the task execution and allows us to model scenarios for each possible outcome. Furthermore, this approach makes it possible to create separate branches inside the process for various error types, which substantially increases verbosity and flexibility of the model.  

![9a0827.png]({{strapiUrl}}/uploads/9a0827_d984111d88.png)

It looks beautiful on paper! But it doesn't work, if you make an API call from the usual `JavaDelegate` or `Spring Bean` by means of the good old `RestTemplate`. (Of course, `RestTemplate` is in itself a synchronous HTTP client that blocks the thread while the request is being completed. But this approach is easier and more familiar to many people than `WebClient`, so we are going to use it.) 

We just need to allow the service task to complete itself, and the process will be able to move forward and switch to the waiting state with the event based gateway. But what to do?  

Well, let's send the HTTP request not from the service task itself, but from a different place. Let the service task initiate this action through an application event. Then everything will be fine: our service task will quickly shoot out an event, and its mission will be immediately accomplished. Then the event will be grabbed by a listener, but that will happen outside the process context. The listener, in its turn, will execute the HTTP request using `RestTemplate`, wait for the response and send one message or another into the process.  

This is what it looks like on a time sequence diagram. We have uncoupled the BPMN process execution and the external service call. The process will go on along one path or another depending on the request result, OK or error.  

![undefined (2).jpeg]({{strapiUrl}}/uploads/undefined_2_79287fdf82.jpeg)

The last little detail: our listener has to be asynchronous; otherwise, it will block the process by itself, and we will again have to wait until the external service condescends to respond. Fortunately, Spring has the `@Async` annotation; when we add it, the method is executed in a separate thread and blocks nothing.  

## Implementing the process in Jmix BPM with the Flowable engine 

Okay, let's move from theory to practice and try to implement a non-blocking external service call from a business process. Supposing that we are receiving addresses from somewhere, and it is necessary to check whether they are real. This check will be done with the help of the  Nominatim service: if the address exists, the service will return a location on the map; otherwise, it returns a `null`.

**Open-source geocoding with OpenStreetMap data** 

> <a href="https://nominatim.org/" target="_blank" rel="nofollow">Nominatim</a> (from the Latin "by name") is a tool that searches for OSM data by name and address and also generates synthetic addresses for OSM locations (reverse geocoding). It also has a limited possibility of searching for objects by their type (pubs, hotels, churches, etc…) It has an API, which we are going to use.  

In the middle of the diagram, you can see a service task named Send request to Nominatim. As we discussed above, the task itself doesn't make the API call, it only sends an application event, which gets caught by our listener. It is not present on the BPMN diagram, but it carries out the most important work, the geocoding as such. After the service task we have the event based gateway set up to handle three options for the process continuation: 
- Normal, when a positive response is received, and real coordinates have been found for the address. 
- Error, when the address turned out to be faked, and the service has returned a null. In this case, the process throws a BPMN error with a certain code, which can be processed in the higher level process.  
- Timeout exit. Naturally, an external service is not always available.  

The external service doesn't have to be down, it can be outside the accessible zone, and the application is not connected to the internet. But the process shouldn't just hang. This situation must be processed correctly. Therefore, we model a `fail retry` and give it three attempts to receive a response. At every attempt the counter is incremented, and after three attempts we throw a BPMN error, but with a different code.  

![undefined (3).jpeg]({{strapiUrl}}/uploads/undefined_3_b21ac05a33.jpeg)

How it is different from the standard approach: 
- The risks related to long transactions in the process are completely eliminated.  
- All exceptional situations are visible and can be further improved. For example, after three attempts we can escalate the task to a human being instead of throwing an error. Or you can invent your own option for this.  

## Implementation 

The `Send request to Nominatim` service task calls the `AddressVerificator` bean: 

```
@Component(value = "ord_AddressVerificator") 

public class AddressVerificator { 

   private static final Logger log = LoggerFactory.getLogger(AddressVerificator.class); 

   @Autowired 

   private ApplicationEventPublisher applicationEventPublisher; 

   public void verify(Order order, DelegateExecution execution) { 

       String processInstanceId = execution.getProcessInstanceId(); 

       if (order.getAddress() != null) { 

           applicationEventPublisher.publishEvent(new RequestSendEvent(this, order, processInstanceId)); 

       } else { 

           log.error("Order # {}: Address is NULL", order.getNumber()); 

       } 

   } 

} 
```
In fact, the `verify` method from this bean only sends a `RequestSendEvent` message with the help of `ApplicationEventPublisher`, and it contains no other logic.  

This message is caught by the `onRequestSendEvent` listener: 

```
@Async 

@EventListener 

public void onRequestSendEvent(RequestSendEvent event) { 

   Order order = event.getOrder(); 

   String processInstanceId = event.getProcessInstanceId(); 

   Point point = geoCodingService.verifyAddress(order.getAddress()); 

   if (point != null) { 

       orderService.setLocation(order, point); 

       sendMessageToProcess("Address OK", processInstanceId); 

       log.info("Order # {}, Address verified: {}", order.getNumber(), order.getAddress()); 

   } else { 

       sendMessageToProcess("Fake address", processInstanceId); 

       log.info("Order # {}, Invalid address: {}", order.getNumber(), order.getAddress()); 

   } 

} 

private void sendMessageToProcess(String messageName, String processInstanceId) { 

   ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() 

           .processInstanceId(processInstanceId) 

           .singleResult(); 

   if (processInstance == null) return; 

   Execution execution = runtimeService.createExecutionQuery() 

           .messageEventSubscriptionName(messageName) 

           .parentId(processInstance.getId()) 

           .singleResult(); 

   if (execution == null) return; 

   runtimeService.messageEventReceivedAsync(messageName, execution.getId()); 

} 
```
It is important for this listener to be asynchronous, because otherwise it will be executed in the same thread with the process, and the task will be completed only when it finishes working.  

> The `@Async` annotation in Spring is used to execute methods in the asynchronous mode. It means that the method, which is annotated by it, will be executed in a separate thread without blocking the main thread where the program runs. This way, the main thread can continue to execute other tasks without waiting for the async method to be completed.  

Then, we call the `verifyAddress` method from the `GeoCodingService` bean, and this method makes the actual call to the Nominatim service. The method returns a point on the map: the Point object. Depending on the result, we send a message to the process, which can be **"Address OK"** or **"Fake address"**. And then the `event based gateway` gets to work. 

The geocoding service executes a typical HTTP request using `RestTemplate`:


```
@Service 

public class GeoCodingService { 

   private final RestTemplate restTemplate; 

   public GeoCodingService(RestTemplate restTemplate) { 

       this.restTemplate = restTemplate; 

   } 

   public Point verifyAddress(String address) { 

       String NOMINATIM_URL = "https://nominatim.openstreetmap.org/search?q={address}&format=json&polygon_kml=1&addressdetails=1"; 

       ResponseEntity<NominatimResponse[]> response = restTemplate.getForEntity(NOMINATIM_URL, 

               NominatimResponse[].class, 

               address); 

       if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) { 

           NominatimResponse[] results = response.getBody(); 

           if (results.length > 0) { 

               double latitude = results[0].latitude(); 

               double longitude = results[0].longitude(); 

               GeometryFactory geometryFactory = new GeometryFactory(); 

               return geometryFactory.createPoint(new Coordinate(longitude, latitude)); 

           } 

       } 

       return null; 

   } 

} 
```
If the service hasn't responded within a certain period of time, the timer goes off and the repeated attempt is carried out. To avoid getting an eternal loop, we use the attempt counter. In theory, after exhausting all the attempts we can escalate the task to an employee, who will make the check-up manually.  

## Conclusion 

When we design a business process, it is important to pay attention to the duration of system task executions and possible exceptional situations, which should be correctly processed. The `fail retry` mechanism should be treated with caution. It was invented a long time ago, and now we have more advanced patterns for such situations.  

By combining the application events and BPMN events, we can uncouple the external service request execution and the task completion, in order to be able to use the `event based` gateway. This approach reduces the risks related to long transactions.  
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Advanced Software for Insurance Automation – Jmix]]></title>
            <link>https://www.jmix.io/blog/insurance-automation</link>
            <guid>https://www.jmix.io/blog/insurance-automation</guid>
            <pubDate>Wed, 13 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_Blog_Industries_Insurance_f44a738a5e.png">Automation solutions in the insurance industry can streamline business operations and improve customer-facing digital capabilities. Insurers looking for competitive advantage should consider the role of automation and industry technology trends to improve the customer experience, business efficiency and profitability.]]></description>
        </item>
        <item>
            <title><![CDATA[Modern Enterprise Architecture: Self-Contained Systems]]></title>
            <link>https://www.jmix.io/blog/modern-enterprise-architecture-self-contained-systems</link>
            <guid>https://www.jmix.io/blog/modern-enterprise-architecture-self-contained-systems</guid>
            <pubDate>Thu, 24 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Modern_Enterprise_Architecture_Process_Variables_8931d8e9fc.png">A pragmatic approach to build billion-dollar apps with a small team.]]></description>
            <content:encoded><![CDATA[A pragmatic approach to build billion-dollar apps with a small team

## Introduction

How can you quickly fail with a Java project? Just pick every new technology from the latest conference without having a clear plan. But how can you build a big, reliable project quickly—even with a small team? The secret is choosing the right architecture and easy-to-use tools like **Jmix**, which helps you build enterprise applications faster and easier.

This article explains a useful software architecture called **Self-Contained Systems (SCS)**.

With SCS, you split your big application into smaller parts, called **domains**. Each domain is like a small, independent application. The key idea is to make these small applications talk to each other very little. This is akin to microservices, but simpler and easier to manage.

We learned about SCS by working on large, complicated projects. In this article, we share what we learned and show how SCS can help solve many real-life problems. We will also talk about how you can build billion-dollar projects using Jmix and how jmix makes it easier to build systems based on SCS quickly.

## The Evolution of Architectures

Software architecture has evolved through several phases, each addressing specific needs:

**1. Early Web Architectures (e.g., MVC)**
Initially, their focus was on delivering static content and simple request-response cycles. As projects grew in complexity, architectures like MVC helped scale codebases.

**2. N-Layer and SOA**
As systems became more interconnected, layered architectures and Service-Oriented Architecture (SOA) emerged to facilitate integration, data exchange, and code reuse. This approach improved internal communication, yet scalability still mainly boiled down to adding layers of code complexity rather than addressing team size or resource constraints.

**3. Microservices Era:** 
Microservices changed the game by decomposing systems into more minor, independently deployable services. Different teams could own services and scale resources (CPU, memory, storage) for specific system parts. Microservices looked like a promising solution in terms of agility, continuous deployment, and architectural freedom. However, they also introduced substantial complexity, requiring intricate DevOps tooling, as well as extensive documentation and coordination.

**4. Disenchantment and Reassessment:**
Over time it became clear that the full scale-out capabilities and complexity of microservices was not for everyone. For many enterprise and e-commerce projects — especially those not operating at the “Big Tech” scale—the overhead brought forward by microservices became burdensome. Teams began looking for a middle ground solution, which preserved some modularity and fault tolerance without incurring the full complexity costs of microservices.

## Self-Contained Systems

![SCS_English_ExtendedArticle 1 (1)_html_e595c411.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_e595c411_f9d11fb2bd.png)

## An Overview of Self-Contained Systems

**Self-contained systems (SCS)** are small, independent applications which, taken together, form one bigger software product. Each SCS application focuses on one specific part (domain) of the whole system. They work separately and don't depend much on each other.

You can think of SCS as something between microservices and a big monolith. Microservices are very small and can be hard to manage. A monolith is easy to build but hard to change. SCS gives you the best parts of both approaches—simple to manage, easy to change, and more stable. If one part fails, the other parts still work.

![SCS_English_ExtendedArticle 1 (1)_html_e26cab7b.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_e26cab7b_04a56472b7.png)

Here, you would typically see diagrams showing clear examples of monoliths, SOA, microservices, and SCS. These diagrams help you understand each architecture. Usually, SCS diagrams show multiple independent domain monolithic applications communicating through simple messages.

**The Philosophy of SCS**

<img src="{{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_b2128ed3_e5ceddc1d5.png" width="300">

The SCS community (notably Innoq) outlines several guiding principles:
1.  **Domain-Centric Decomposition:** Break down the system by domain, with each domain as an autonomous subsystem. 
2.  **Domain Ownership:** Subsystems should not expose or import internal domain objects unnecessarily.
3.  **Minimal Overhead:** Each subsystem resembles a microservice in architecture but can remain a monolith internally.
4.  **Service Orientation:** Internally, a subsystem can contain multiple microservices, but externally it acts as a single unified system.
5.  **Dedicated Databases:** Each subsystem manages its own data storage.
6.  **Technological Freedom:** Teams choose the best technology stack without strict constraints from other subsystems.
7.  **Asynchronous Communication**: Domains usually use REST APIs or simple asynchronous message brokers, depending on the situation (as an exception, they can also be synchronous).
8.  **Communication Independence:** If one subsystem is down, others should continue operating or gracefully handle the unavailability. By the way, cross-system communications do not have to break any business processes just because of the unavailability of dependent subsystems.
9.  **Team Alignment:** Each subsystem is owned by a single team (though one team can own multiple subsystems).
10.  **Minimal Coupling:** Dependencies between subsystems should remain low. Using clear UI integration strategies can help reduce coupling further.
11.  **Reusability:** Common functionality, UI components, or DTOs can be managed in shared libraries/toolkits.
12.  **Separate UIs with Consistent Style:** Each subsystem has its own user interface. However, all UIs should follow the same style using a shared UI toolkit or clear style guidelines.
13.  **Unified Look and Feel:** Users should feel like they are using one application despite the presence of multiple subsystems. All subsystems should look and behave similarly, using a shared UI kit.
14.  **Seamless Integration:** From a user’s perspective, the subsystems present a unified experience (e.g., via hyperlinks, iframes, or a root layout).
15.  **Bi-Directional Links:** Subsystems should allow cross-navigation via hyperlinks where it makes sense.

These principles are guidelines, not strict rules. Following them closely helps avoid future problems. Also, principles 1–11 might look similar to what we had with microservices. However, the last three (12–15) are SCS-specific. They ensure that each domain’s user interface looks good and feels easy to use, even though the domains are separate. They also help domains connect smoothly for the user.

## Advantages and Disadvantages of SCS

### Advantages
- **Fault Tolerance:** If one subsystem fails, the others can still continue working normally.
- **Independence for Teams:** Each subsystem can be developed and maintained separately.
- **Clear Domain Boundaries:** Encourages separating functionality clearly into independent modules or domains.
- **Keeps Monolithic Simplicity:** Allows fast development and easy changes, similar to building one big application.
- **Independent Deployments:** Subsystems can be updated, scaled, and released independently.
- **Good for Enterprise:** Usually simpler and cheaper than microservices, especially for large business applications.

### Disadvantages
- **Complex UI Integration:** Building multiple subsystems that look and feel like one application can be tricky.
- **Communication Effort:** Needs careful planning to connect subsystems, unlike a simple monolithic application.
- **Deployment Complexity:** Deploying SCS is simpler than microservices, but still more complex than a single monolith.
- **Extra Documentation:** You must clearly document how each subsystem works and interacts with others.
- **Shared UI Components:** All teams must use common UI tools or guidelines, which takes extra effort.
- **UI Performance Challenges:** Improving user interface speed and responsiveness is often harder across multiple subsystems compared to a single large application.

**Note**: For many business or e-commerce projects, these disadvantages are less important than having reliable and clear domain-specific features.

## Why Jmix is a Good Fit for SCS?

Self-Contained Systems (SCS) is a practical and proven architectural pattern for building modular software. But like any other architectural solution, its success depends on the right tools. In practice, we’ve found that Jmix aligns well with the core ideas of SCS, making it easier to implement in real-world scenarios.

Here's exactly how Jmix supports SCS projects:

- **Rapid Domain Development:** Quickly builds separate, independent domains with ready-to-use tools and built-in patterns.
- **Built-in Security and User Management:** Jmix handles authentication, permissions and roles out-of-the-box, significantly reducing development complexity.
- **Simplified Domain Integration:** Jmix’s built-in REST APIs simplify the process of connecting multiple domains smoothly.
- **Consistent and Modern UI:** With the additional help of Vaadin,, Jmix provides easy-to-build, modern user interfaces without additional frontend overhead, allowing each domain to maintain UI consistency.
- **Robust Workflow Automation:** Built-in support for business process automation (using BPM tools like Flowable) allows domains to interact reliably and asynchronously.
- **Flexible Technology Base (Spring Boot):** Built upon Spring Boot, Jmix offers extensive flexibility and compatibility with existing Java and Kotlin ecosystems.
- **Scalable and Maintainable Monoliths:** Jmix helps build clear, maintainable Java or Kotlin monoliths without unnecessary complexity, aligning well with SCS principles of simplicity and low coupling.

Our focus on SCS comes directly from observing how naturally Jmix supports and simplifies this architectural approach. Combining SCS with Jmix results in easier, faster, and more reliable software development for enterprise-level projects.

For instance, consider a food delivery application. With Jmix, we rapidly set up distinct domains like orders, restaurants, and couriers. Each domain has its own database, UI, and business logic, while Jmix ensures straightforward integration between them. Complex tasks, such as assigning couriers or handling restaurant orders, become significantly simpler.

Later in this article, we'll show you precisely how to build this food delivery application using Jmix and further explore the practical benefits of this combination.

Before diving into how Jmix fits into SCS, let’s first explore a straightforward case where the SCS approach clearly solves common architectural challenges. This will help show why SCS makes sense—even before we bring in any specific technology.

## An Ideal Scenario for SCS: AI Chat Platform

Imagine a platform where you can chat with an AI assistant, generate images, analyze documents, and even create code — all in one place. For example, think about something like OpenAI’s ChatGPT, but with extra features for images, files, and code. To the user, this looks like one big product. But inside, it is made up of several smaller, independent systems.

<img src="{{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_a47d8b93_65afdf956c.png" width="500">

### Why Not Monolith or Microservices?

- If you build everything as one large monolith, it quickly becomes hard to manage and scale.
- If you go with full microservices, you might spend too much time and money on it.

**Self-Contained Systems (SCS)** offer a third way. Each big feature (chat, image generation, document analysis, code generation) becomes a standalone system — called a domain of subsystem. Each domain has its own UI, logic, and database. Still, from the user's point of view, it all works as a single product.

## Applying SCS to an AI chat platform

![SCS_English_ExtendedArticle 1 (1)_html_9f567ccb.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_9f567ccb_cd69f7709d.png)

### Domains as Subsystems

Let’s break this platform into clear, independent domains:
- **Chat System:** Handles conversations with the user. It can use internal services like language models or embeddings, but always presents one simple interface.
- **Image Generation System:** Creates images from user’s prompts.
- **Document Analysis System:** Lets users upload and analyze documents.
- **Code Generation System:** Helps users by creating code based on their questions or prompts. It can use AI models or special algorithms to generate and explain code.
- **Integrations / Partner Services:** Connects to third-party services or external APIs.

Each subsystem:
- Has its own user interface (UI)
- Manages its own database
- Runs its own backend application

Sometimes, a subsystem may also include smaller internal services for extra processing or calculations. Subsystems can communicate through APIs or asynchronous messages. For example, if a user asks for image generation inside the Chat System, it sends a request to the Image Generation System and either receives a result or, if that system is unavailable, simply informs the user that the feature is not ready right now. This kind of seamless interaction between subsystems makes the whole platform feel like a single, unified product—even though it is built from separate parts.

<u>This design lets every domain develop and improve independently, but together they create one smooth product for the user. </u>

## Unifying the UX

Even though each domain can run on its own, users want the whole platform to feel like one product. SCS gives you several simple ways to create a unified and smooth experience for everyone.

![SCS_English_ExtendedArticle 1 (1)_html_828b602b.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_828b602b_7e54f78f3c.png)

### Root Layout and Navigation

Usually, there is a main application — sometimes called a “root layout”. 

This part provides global navigation and **look and feel**. The main app can show other domains in iframes or by linking to them. All domains use the same UI kit to keep the style familiar for the user.

![SCS_English_ExtendedArticle 1 (1)_html_41f3c8f0.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_41f3c8f0_fab1e95eb9.png)

**Example layout:**
- **Top navigation** with links to Chat, Image Generation, Document Analysis, etc.
- **Main content area** displays the chosen subsystem’s UI (for example, via an iframe).

**Extra panels** can show history or context (like recent chats or images).

### Hyperlinks and Context Passing

Domains can link to each other using special URLs. For example, after generating an image, the Image System can give a link to the Chat System with the image’s ID. When the user clicks on it, the chat opens and shows the image inside the conversation. This way, domains stay separate, but users get a smooth workflow.

### Asynchronous Integration

Sometimes, domains send requests and wait for responses in the background. 

For example, if the user asks for an image in the Chat System, the chat sends a request to the Image Generation System. When the image is ready, it sends a link back. If the image system is offline, the chat just tells the user “this feature is not available right now.” This keeps the experience smooth and reliable, even if some parts are down.

![SCS_English_ExtendedArticle 1 (1)_html_5dd63844.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_5dd63844_98ef8a6d06.png)

## Cross-system interactions: A practical example

Let’s say a user currently interacts with the Chat (GPT) System and requests image generation. In a typical synchronous or hybrid approach the system world:

Check Availability: The GPT System pings the DALL·E (Image Generation) System to confirm that it is online.
1. **Delegate Request:** If available, the GPT System forwards the user’s prompt (e.g., “Generate a robot dancing on Mars”) to the DALL·E subsystem.
2. **Await Response:** The GPT System waits for the outcome (either synchronously or asynchronously).
3. **Provide Feedback:**
        a. **Success:** Returns the generated image link or a small preview to the user.
        b. **Failure:** If DALL·E is down, the GPT System immediately replies, “Image Generation is unavailable now.”

This setup ensures that each subsystem is autonomous. A DALL·E failure doesn’t break chat functionality — it only affects the image request.

### Autonomy, Resilience, and Flexibility

**Why this is useful:**
- Each domain can work, scale, and update by itself.
- If one domain fails, others keep running.
- New domains (like Audio Generation) can be added easily later—just plug them in.

**Minimal Inter-system Coupling:**
- Each domain hides its inner logic.
- Data is never shared directly — domains use stable APIs to talk.
- Teams can update or improve one domain without breaking others.

**User-Centric by DDD Approach:**
- Each domain matches a user’s real task (chat, images, docs).
- Each domain knows its job well, so it is easy to improve over time.

## Summary: Why SCS Works Here

In an SCS-based AI platform, each domain is like a “mini-app.” It manages its UI, business logic, and data independently. The root layout brings them together with iframes, links, and shared UI. The whole platform looks and works as one product but is easy to scale and maintain.

**What this gives?**

Fault tolerance — one domain fails, the rest keeps working.

- Scalability: scale only the most busy domains.
- Flexibility: add or change features with little effort.
- User focus: architecture matches how users see the product.

## The Quasi-SCS example

**Yet another food delivery demo**

Food delivery is a simple, real-world scenario everyone understands. It has independent subsystems (orders, restaurants, couriers), asynchronous flows, and easy roles — the perfect sandbox for demonstrating SCS. In fact, it’s even clearer than the AI chat example from earlier.

**Why Jmix?**

Jmix lets you build complex business logic, UI, and user roles fast. Out-of-the-box BPM (Flowable) handles business processes, and security is easy with Keycloak. We’re showing practical, step-by-step SCS architecture — not just theory, but real code.

### End-to-End Business Flow

Let’s see how a real food delivery process works before we jump into code.

**Domain Breakdown: Who Owns What?**

Let’s start by mapping out the key domains (subsystems) in the food delivery scenario:

- **Order System:**
Handles all user-facing interactions: selecting food, placing orders, tracking order status. Orchestrates the business process and acts as the “brain” of the flow.
- **Restaurant System:**
Manages restaurant data, menus, food items, and processes requests to prepare orders. Restaurant admins confirm the order preparation.
- **Courier System:**
Handles couriers, assigns delivery tasks, and updates order delivery status.

<u>Note:</u> In a full enterprise implementation, you’d likely have additional domains for payments, notifications, reviews, etc. For this demo, we keep it to three for clarity.

#### Step-by-step process

Here’s what happens with business process, step by step, from the user’s perspective:

1. User places an order:
    - Views the restaurant list (from Restaurant System).
    - Builds a cart, places an order.

2. Order System launches a business process:
    - A new BPMN process instance tracks the order.

3. Restaurant confirmation:
    - The process sends a request: “Can you cook this order?”
    - Waits for the restaurant admin to accept.

4. Cooking confirmed:
    - Restaurant admin confirms in their UI (also Restaurant System).
    - Process resumes.

5. Courier assignment:
    - Process requests a courier from Courier System.
    - Waits for a courier to accept.

6. Delivery:
    - Courier marks as delivered.
    - Process ends, status is updated.


All long-running "waits" are handled asynchronously, thanks to Jmix BPM Engine.

#### Delivery business flow

Before we dive into the code, let’s look at a high-level diagram that illustrates the business process for food delivery. This will help you get a sense of the overall flow before we break it down step by step.

![SCS_English_ExtendedArticle 1 (1)_html_11c932ba.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_11c932ba_3e10bb9976.png)

You might notice that I often use “monolith-style” diagrams to illustrate the delivery flow—even though our project is based on SCS principles. There’s a simple reason:

I built two versions of the application — one as a classic monolith and another using SCS. The monolithic version is much easier to visualize and explain, especially for readers who are new to these patterns. Our open-source example (see GitHub) uses the SCS approach, but is intentionally simplified — only three domains are implemented, and the BPMN isn’t 100% production-ready. For this article, I’ll focus on the simplified app, not a full-scale enterprise implementation.

If you really want to dive deep into a canonical SCS diagram for food delivery, feel free to check the full architecture in the repository. 

But my advice is simple: <u>Don’t stick too much to diagrams and business requirements.</u>

Focus instead on the core ideas and follow the step-by-step walkthrough below.

<img src="{{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_c14da5ea_1b570a157d.png" width="300">

By the way, BPMN diagrams make it much easier to understand how the process flows. So, if the system diagrams seem overwhelming, just skip ahead to the BPMN examples — they’ll clarify the process much more clearly.

Below BPMN diagrams make the process much clearer, so feel free to skip ahead to those examples if the system diagrams seem too complex.

![SCS_English_ExtendedArticle 1 (1)_html_da170bf9.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_da170bf9_43cea14b22.png)

#### BPMN in Action

Orchestration is managed in a BPMN process:

- **Service tasks (Gear wheel):** Automated steps (like HTTP calls to Restaurant System).
- **User tasks (User icon):** Wait for admins or couriers.
- **Timers / errors (Clock):** Retry, timeout, or alternate flows.

We’ll see exact BPMN XML fragments in the next sections. Now, let’s look at how the Restaurant System is built in Jmix — with real code, REST endpoints, and UI screens.

## Building all together

Let’s start from the Restaurant domain. Why? The Restaurant System is a core domain in our food delivery SCS example. This is where restaurant admins manage menus, food items, and confirm cooking requests. Let's see how we implement this subsystem in Jmix — step by step, with real code and business logic.

**1. Defining the Main Entities**

First, we define the main data structures.
For restaurants, we need entities like:
- Restaurant — the main entity for a restaurant.
- RestaurantMenu — a menu belonging to a restaurant.
- RestaurantMenuItem — individual dishes, belongs to the menu of the restaurant.

**Example Jmix entity for Restaurant:**

```
@JmixEntity
@Table(name = "RESTAURANT")
@Entity
public class Restaurant {
    @JmixGeneratedValue
    @Id
    private UUID id;

    private String name;
    private String description;
    // Optional: image/icon as attachment
}
```
Other entities are similar, each with references back to Restaurant.

**2. Creating UI Screens with Jmix FlowUI**

With Jmix, you don’t need to write boilerplate UI code.
You can generate or customize CRUD screens for all entities:

- **Restaurant List Screen:** Shows all restaurants.

![SCS_English_ExtendedArticle 1 (1)_html_ba531f5f.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_ba531f5f_e473f10eda.png)

- **Restaurant Detail Screen:** Allows admins to edit adn to add menus and dishes.

![SCS_English_ExtendedArticle 1 (1)_html_dcb3b5cb.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_dcb3b5cb_51bcc55853.png)

- **Menu/Item Screens(Pages):** Manage menu composition.

![SCS_English_ExtendedArticle 1 (1)_html_3b4b2c4b.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_3b4b2c4b_a3fb5ccae4.png)

The screens are defined declaratively and can be customized as needed.

<u>Note:</u> In Jmix 2 any web pages are named “Views”, in the older  Jmix versions the name was “Screens”.

**3. Exposing REST API for Inter-Domain Communication**

To allow the Order System to fetch restaurants/menus, we expose a simple REST API:

```
@Secured(FullAccessRole.CODE)
@RestController
@RequestMapping("/api/v1")
public class RestaurantController {

    @Autowired
    private RestaurantRepository restaurantRepository;

    @GetMapping("/restaurants")
    public List<RestaurantDTO> listRestaurants() {
        return restaurantRepository.findAll().stream()
            .map(restaurant -> {
                var dto = new RestaurantDTO();
                dto.setId(restaurant.getId());
                dto.setName(restaurant.getName());
                dto.setDescription(restaurant.getDescription());
                // Set icon if available
                return dto;
            })
            .toList();
    }

    @GetMapping("/restaurants/{id}")
    public RestaurantDTO getRestaurant(@PathVariable UUID id) {
        // fetch and map Restaurant to DTO
    }

    @GetMapping("/restaurants/{restaurantId}/menus")
    public List<RestaurantMenuDTO> listMenus(@PathVariable UUID restaurantId) {
        // fetch and map menus for given restaurant
    }
}
```

**4. Confirming Cooking Requests**

Orders are passed from the Order System via a REST call, which the restaurant admin needs to confirm.

**Receiving a cook request:**

```
@PostMapping("/restaurants/{restaurantId}/cook")
public String getRestaurantCookRequest(@PathVariable UUID restaurantId, @RequestBody OrderDTO orderDTO) {
    // Save a new cook order for admin review
    cookOrderService.submitNewCookOrderFromDTO(orderDTO);
    return "Accepted";
}
```

Admins see pending cook requests in their Jmix UI and can accept them.

![SCS_English_ExtendedArticle 1 (1)_html_7526ef41.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_7526ef41_0967adceba.png)

**4a. The Service Layer: Business Logic in Jmix**

Let’s look at the CookOrderService, which handles business logic for creating new cooking requests.

Here’s a simplified version of the relevant method:

```
@Service
public class CookOrderService {
    @Autowired
    private RestaurantRepository restaurantRepository;

    @Autowired
    private DataManager dataManager;

    public void submitNewCookOrderFromDTO(OrderDTO orderDTO) {
        CookOrderRequest cookOrderRequest = dataManager.create(CookOrderRequest.class);
        cookOrderRequest.setOrderId(orderDTO.getOriginOrderId());
        cookOrderRequest.setIsDone(false);
        cookOrderRequest.setRestaurant(restaurantRepository.getById(orderDTO.getRestaurantId()));
        cookOrderRequest.setCookingItems(createCookingListFromDTO(cookOrderRequest, orderDTO));
        dataManager.save(cookOrderRequest);
    }

    // Helper for creating cooking item list (not shown for brevity)
}
```
What happens:

- This method receives an order, creates a CookOrderRequest entity, links it to the restaurant, and saves everything to the database.
- Jmix’s DataManager handles persistence and transactions, reducing boilerplate.

This is the kind of domain service you’ll find in each subsystem. It keeps REST controllers thin and business rules clear.

**5. How it fits into the BPMN process**

The Restaurant System is involved at these BPMN steps:

- Receives an automated service task ("request restaurant to cook").
- Waits for a user task (admin confirmation).
- Sends callback to the Order System to resume the process.

(BPMN XML fragment — as promised!)

```
<serviceTask id="Activity_1jhcclq" name="Request Restaurant to Cook"
    flowable:async="true"
    flowable:expression="${requestRestaurantCookStep.execute(execution)}"
    jmix:taskType="springBean"
    jmix:beanName="requestRestaurantCookStep">
  <!-- ... -->
</serviceTask>
<userTask id="WAIT_RESTAURANT_CALLBACK_TASK" name="Wait for Restaurant Confirmation">
  <!-- ... -->
</userTask>
```
**Key Takeaways**

- **Clear domain boundary:** Restaurant System manages only its own data and UI.
- **Integration is explicit:** All cross-domain operations are via REST API, not direct DB calls.
- **Jmix FlowUI + REST = quick setup:** UI and APIs are generated or customized fast.
- **Human in the loop:** Restaurant admin interacts via UI, tying into the BPMN flow.

### How it fits into the BPMN Process

The BPMN engine (Flowable, integrated in Jmix) orchestrates the entire food delivery process as a long-running workflow. Each external interaction (like waiting for a restaurant admin to confirm cooking) is represented as a User Task in BPMN.

**How does the callback work?**

- When the admin in the Restaurant System confirms a cooking request, the system sends an HTTP callback to the Order System.
- The Order System finds the paused BPMN process instance for that order and moves it to the next stage.

**Example: Continuing the Order Process after Restaurant Confirmation**

```@PostMapping("/orders/{orderId}/restaurantstep/{restaurantId}")
public void continueOrderRestaurantStep(@PathVariable String orderId, @PathVariable String restaurantId) {
    orderProcessManager.continueProcessByRestaurantStep(orderId, restaurantId);
}
```
**Service method to continue the process:**

```
public void continueProcessByRestaurantStep(String orderId, String restaurantId) {
    OrderEntity order = orderRepository.getById(UUID.fromString(orderId));
    // Check if the callback is from the correct restaurant
    if (!order.getRestaurantId().toString().equals(restaurantId)) {
        throw new RuntimeException("Illegal restaurant callback");
    }
    // Find the waiting user task in the BPMN process and complete it
    continueUserTaskInProcess(orderId, "WAIT_RESTAURANT_CALLBACK_TASK");
}
```

```
private void continueUserTaskInProcess(String orderId, String taskDefinitionId) {
    ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
            .processInstanceBusinessKey(orderId)
            .singleResult();
    Task userTask = taskService.createTaskQuery()
            .processInstanceId(processInstance.getId())
            .active()
            .taskDefinitionKey(taskDefinitionId)
            .singleResult();
    taskService.complete(userTask.getId());
}
```
**What does this achieve?**

- The BPMN process resumed exactly at the point where it was waiting for confirmation.
- The workflow then moves on to the next automated or manual step (e.g., requesting a courier).

**BPMN XML snippet for this step:**

```
<userTask id="WAIT_RESTAURANT_CALLBACK_TASK" name="Wait for Restaurant Confirmation">
  <extensionElements>
    <jmix:formData type="no-form" />
  </extensionElements>
  <incoming>Flow_0b7vho3 (randomly generated id’s of next task)</incoming>
  <outgoing>Flow_1wegar9 (randomly generated id’s of outgoing task)</outgoing>
</userTask>
```

This clear separation between service logic, UI, and the business process state makes your application resilient and easy to extend. If something goes wrong (restaurant doesn’t confirm in time, etc.), you can handle it in the BPMN diagram (e.g., add timeouts, errors or  retries).

### Courier Assignment and Delivery

After the restaurant confirms the order, the process requests a courier and tracks the delivery. Everything is organized just like before: via dedicated REST requests and user/service tasks in BPMN.

**Requesting a Courier (Service Layer)**

When the BPMN process reaches the “Find Courier” step, a service task sends an HTTP request to the Courier System to publish a new delivery task:

```
@Service
public class RequestCourierDeliveryStep extends AbstractTransactionalStep {

    private final CourierClient courierClient;
    private final OrderService orderService;

    @Override
    protected void doTransactionalStep(DelegateExecution execution, OrderEntity order, SaveContext saveContext) {
        String username = getVariable(execution, PROCESS_USER_KEY);
        String subjectToken = exchangeOidcTokenForUser(username);
        // Send request to Courier System
        String result = systemAuthenticator.withUser(username,
                () -> courierClient.publishCourierDeliveryRequest(order.getId(), orderService.convert(order), subjectToken));
        order.setStatus(DraftOrderStatus.WAIT_FOR_COURIER);
        saveContext.saving(order);
    }
}
```
**CourierClient:**

```
public String publishCourierDeliveryRequest(Long orderId, OrderDTO orderDTO, String subjectToken) {
    String url = MessageFormat.format("{0}/api/v1/couriers/delivery/{1,number,#}", courierUrl, orderId);
    return getApi(url, HttpMethod.POST, new ParameterizedTypeReference<String>() {}, orderDTO, subjectToken);
}
```
**Courier System: Accepting a Delivery**

A courier logs into the corresponding system, sees new orders, selects one, and the system sends a callback HTTP request back to the Order System:

```@PostMapping("/orders/{orderId}/courierstep/{courierId}")
public void continueOrderCourierStep(@PathVariable String orderId, @PathVariable String courierId) {
    orderProcessManager.continueProcessByCourierStep(orderId, courierId);
}
```

**Process continuation on courier callback:**

```public void continueProcessByCourierStep(String orderId, String courierId) {
    OrderEntity order = orderRepository.getById(UUID.fromString(orderId));
    if (!order.getCourierId().toString().equals(courierId)) {
        throw new RuntimeException("Illegal courier callback");
    }
    continueUserTaskInProcess(orderId, "COURIER_WAIT_FOUND_TASK");
} 
```

In UI from Courier perspective this step described below:

![SCS_English_ExtendedArticle 1 (1)_html_bc5170f4.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_bc5170f4_1283e896ab.png)

**BPMN XML Snippet: Waiting for Courier**

```<userTask id="COURIER_WAIT_FOUND_TASK" name="Wait for Courier">
  <extensionElements>
    <jmix:formData type="no-form" />
  </extensionElements>
  <incoming>Flow_1f3t4wk</incoming>
  <outgoing>Flow_1f0p9t6</outgoing>
</userTask>
```

**Delivery Completion**

Once the courier delivers the order, they call another endpoint in the Order System:

```@PostMapping("/orders/{orderId}/delivered")
public void continueOrderDeliveredStep(@PathVariable String orderId) {
    orderProcessManager.continueProcessByDeliveredStep(orderId);
}
```

```public void continueProcessByDeliveredStep(String orderId) {
    // Complete the user task and advance the BPMN process
    continueUserTaskInProcess(orderId, "COURIER_DELIVERED_TASK");
}
```

Which we call from UI in Courier system:

![SCS_English_ExtendedArticle 1 (1)_html_47708847.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_47708847_a99a643688.png)

**BPMN XML Snippet: Delivery Wait**

```<userTask id="COURIER_DELIVERED_TASK" name="Wait for Delivery">
  <extensionElements>
    <jmix:formData type="no-form" />
  </extensionElements>
  <incoming>Flow_1c7s5el</incoming>
  <outgoing>Flow_123t2l0</outgoing>
</userTask>
```

Now, from the client’s perspective the delivery request with the DONE status looks as follows:

![SCS_English_ExtendedArticle 1 (1)_html_465b067f.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_465b067f_3646767b68.png)

*Why is this powerful?*

- Each domain interacts through clear API boundaries and the BPMN-controlled process state.
- All “waiting” and “human” steps are managed in BPMN — which provides convenient support for timeouts, cancellation, escalation, or retries.
- No tight coupling or shared state between systems: each subsystem can go offline, be replaced, or scaled, and the process will just “pause” at the right place.

Note: For demo purposes, I put BPM Engine into the Order System, but for more stability, it is better to have Engine as a Standalone server (or as a System).

### Error Handling, Timeouts, and Final Delivery: BPMN and Jmix Patterns

In real business processes, things go wrong: a restaurant might not confirm, a courier might disappear, or a network glitch could interrupt the flow.
SCS and BPMN allow you to design for resilience—handling these failures explicitly, not sweeping them under the rug.

**Handling Errors and Timeouts (BPMN)**

BPMN lets you model timeouts and errors directly in the process definition, so your code stays simple, and the business logic stays visible.

**Example: Timer on Restaurant Confirmation**

Suppose, the restaurant admin doesn’t confirm the order in time. In the BPMN, we add a timer boundary event to the “Request Restaurant Confirmation” step:

```<boundaryEvent id="TIMER_ON_RESTAURANT" attachedToRef="Activity_1jhcclq">
  <outgoing>Flow_1nr0tno</outgoing>
  <timerEventDefinition>
    <timeDuration>PT1M</timeDuration>
  </timerEventDefinition>
</boundaryEvent>
<sequenceFlow id="Flow_1nr0tno" sourceRef="TIMER_ON_RESTAURANT" targetRef="Activity_05ssv9d" />
```

If the timer fires (e.g., after 1 minute or in terms of BPMN - PT1M), the process moves to an “Order Cancelled” step, and the user gets notified:

```<task id="Activity_05ssv9d" name="Mark order as cancelled">
  <incoming>Flow_1nr0tno</incoming>
  <outgoing>Flow_0hj5ypr</outgoing>
</task>
```

```<endEvent id="Event_0bg2i8n" name="Order Cancelled">
  <incoming>Flow_0hj5ypr</incoming>
</endEvent>
```

Similar timers can be added for courier assignment and delivery.

**Clean Error Propagation**

Because the BPMN engine drives the process, your service code can stay focused: throw an error, and the process will handle it.

If any REST request fails (network error, HTTP 500, wrong input), you can catch it and throw a BPMN error. The process will move to the error handler, showing the user a clear message or triggering a retry.

**Example in Java:**

```try {
    // ... REST call to Restaurant System
} catch (Exception ex) {
    throw new BpmnError("ORDER_CANCEL_ERROR", "Could not confirm order with restaurant");
}
```

#### Final User Experience

 If you need better understanding of  what is happening in user flow, this [sub-article in the GitHub Repository](https://github.com/KartnDev/FoodDeliveryJmix/blob/main/docs/project-usecase/README.md) is for you.

- The user always sees a clear, up-to-date order status in the Order System UI.
- If something fails (timeout, cancellation), the UI shows an error message or “please try again.”
- All process transitions are visible to admins and users — nothing is hidden in backend logs.

### Summary: Why SCS + Jmix + BPMN?

- **Separation of Concerns:** Each subsystem is fully independent: failure in one of the subsystems does not cascade
- **Explicit Processes:** BPMN puts the real business flow front-and-center. Business users and developers can read and update it.
- **Rapid Iteration:** Jmix + Flowable BPM lets you add steps, UI, or logic without rewiring everything.
- **Enterprise-Ready:** Security (Keycloak), forms/UI, and process orchestration are all handled without tons of custom boilerplate.

### Conclusion for the Jmix Delivery Example

By walking through a real-world food delivery scenario with Jmix, you’ve learned:

- How SCS breaks up complex domains and business flows into truly autonomous systems.
- How Jmix helps rapidly build robust UIs, APIs, and back-office screens for each domain.
- How BPMN lets you orchestrate (It is unclear what the author is trying to say here), monitor, and evolve end-to-end processes that span domains.
- How clear API boundaries, process-driven integration, and explicit error handling make your project more resilient and maintainable.

**But here’s the twist:**

Our implementation isn’t a textbook SCS. We made a few pragmatic adjustments:

- **We skipped a root layout shell** — every domain has its own UI, and users simply access the needed subsystem directly (or put end-to-end bidirectional links like “Want to become courier? -> Courier system link”)
- Instead of **pure asynchronous** messaging between domains, we used **BPMN-driven orchestration** for all long-running or “waiting” steps. This actually gave us a more robust and transparent business process, easier to troubleshoot and extend.

<u>Note:</u> Sometimes, “bending the rules” makes the architecture even stronger for your team and use case.

If you want to explore or extend this demo, check out the full project on [GitHub](https://github.com/KartnDev/FoodDeliveryJmix/).

And remember: SCS isn’t about buzzwords — it’s about building resilient, understandable systems with the right tools for the job.

**What about the “root layout” dream?**

Of course, there are scenarios where you need a truly unified user experience across all subsystems — a seamless UI, deep cross-domain navigation, and the feeling that everything is “one big product.” The classic example? **Amazon’s ecosystem**.

Let’s wrap up with a quick look at how SCS can power even the most integrated, product-like platforms.

## Amazing “root layout” case: Amazon’s ecosystem

Amazon’s website is a textbook “root layout” example for Self-Contained Systems, even if it isn’t called that explicitly. To the user, it’s a single unified experience. Behind the scenes, it’s built from autonomous subsystems — each responsible for a major part of the business.

![SCS_English_ExtendedArticle 1 (1)_html_95172f7.jpg]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_95172f7_9999fe2ced.jpg)

It might not publicly brand itself as employing Self-Contained Systems, but its vast range of services can be conceptualized similarly. Amazon’s platform appears as a single, unified website to the end-user. However, underneath the hood, you can imagine multiple autonomous subsystems:

- **Product Catalog and Search:** Provides product listings, filters, and recommendations.
- **Shopping Cart and Checkout:** Manages the cart, payment methods, discounts, and order confirmations.
- **Account Management and Settings:** Handles user profiles, order histories, and personal data.
- **Streaming Services (Prime Video, Music):** Each run as a self-contained subsystem with its own UI and logic, yet remains accessible from the main navigation.

![SCS_English_ExtendedArticle 1 (1)_html_e9006d15.png]({{strapiUrl}}/uploads/SCS_English_Extended_Article_1_1_html_e9006d15_a3c64d5e9c.png)

From a user’s perspective, navigating from “Shop by Department” to “Prime Video” is seamless—even though these could be entirely different domains and tech stacks. In reality, these services communicate minimally (often via REST APIs or well-defined contracts), but the UI remains consistently branded for a cohesive look and feel. If a subsystem like Prime Video experiences issues, the rest of Amazon is still available—demonstrating fault tolerance and autonomy.

## Conclusion

<u>**Self-Contained Systems (SCS)**</u> offer a practical middle ground between classic monoliths and sprawling microservices. Whether you’re building a modern AI platform, a food delivery service, or a complex e-commerce site, SCS principles help you:

1. Divide your application into well-defined, domain-focused subsystems
2. Enable team autonomy, independent deployment, and robust fault isolation
3. Deliver a seamless, unified experience to your users

There’s no one-size-fits-all in software architecture. But with SCS, you gain flexibility—adopting the principles fully or partially, as your business and the tech context demand. The result: systems that are easier to change, more resilient to failure, and closer to how users and teams actually work.
Adopt SCS where it fits — and enjoy software that scales and evolves without unnecessary pain.

<style>
  .blog-article__content img {
    max-width: 80%!important;
}
ol li ul {
    margin-top: 6px;
}
</style>



]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Digital transformation in the banking and finance industry – Jmix]]></title>
            <link>https://www.jmix.io/blog/banking</link>
            <guid>https://www.jmix.io/blog/banking</guid>
            <pubDate>Wed, 23 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_Blog_Industries_Banking_b7d3ac873b.png">Today digital transformation can solve most of the challenges in the financial industry. Continuous automation and digitalization is the only way to keep competitive under constantly changing business requirements.]]></description>
        </item>
        <item>
            <title><![CDATA[Webinar What’s new in jmix 2.6]]></title>
            <link>https://www.jmix.io/blog/webinar-whats-new-in-jmix-2-6</link>
            <guid>https://www.jmix.io/blog/webinar-whats-new-in-jmix-2-6</guid>
            <pubDate>Mon, 21 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/What_s_New_in_Jmix_2_6_1080h1920_without_date_110aef21d6.png">This webinar covered the new features and enhancements in the latest version of Jmix and our roadmap for future updates.]]></description>
            <content:encoded><![CDATA[Release Jmix 2.6 is here, and we are glad to share more details about key updates to this new version with you!

We recommend reading an [article](https://www.jmix.io/blog/jmix-2-6-is-released/) about the release and watching a webinar recording below to learn about all the features.

Speakers of the webinar:

Gleb Gorelov, Tech lead
Konstantin Krivopustov, Head of Engineering
Viktor Fadeev, Product Manager

What we discussed:
- AI Assistant in Studio
- Switch Component
- Masquerade 2.0 - new testing lib
- Tabbed Application Mode Improvements and new UI components
- Message Templates improvements
- Changes in Dynamic Attributes Views

We also covered the Subscription Plans Update and what it means for teams.

You can watch the recording of the workshop on our [YouTube-channel](https://www.youtube.com/live/BXILpeI7fok?si=pzq1UKjRO_VEd-kL).

<iframe width="560" height="315" class="b-youtube-player" src="https://www.youtube.com/embed/BXILpeI7fok?si=p1k-NRXj9NP6Vj2b" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[B2B App Delivery Models Unpacked]]></title>
            <link>https://www.jmix.io/blog/b2b-app-delivery-models-unpacked</link>
            <guid>https://www.jmix.io/blog/b2b-app-delivery-models-unpacked</guid>
            <pubDate>Thu, 17 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Delivery_Mode_Unpacked_221ed85ca2.png">In this article, we are going to talk about how to build a successful delivery strategy using Jmix.]]></description>
            <content:encoded><![CDATA[## Introduction

In this article, we are going to talk about how to build a successful delivery strategy using Jmix. Once you decide to start a new project with Jmix, you need to think about how you will deliver value to your customers in the most effective way. Failing this milestone at the very beginning can easily break the whole project when you start scaling and maintaining it. Let’s see how it may happen with the story of Ben.

<img src="{{strapiUrl}}/uploads/Jmix_Delivery_Models_Unpacked_Article_rev6_html_334920f1_cd341dcca3.png" width="380" alt="seasoned software engineer who one day decided to create his product and found himself quite successful">

## Ben’s Story

There is nothing unusual about Ben’s story — on the contrary, you might call it typical for our day and age, and many of our readers might find themselves in a similar situation one day. It’s a story of a seasoned software engineer who one day decided to create his product and found himself quite successful at first. He built a risk management app according to some local regulations, found a niche, a market for the product, and acquired his first 10 customers in just 9 months.

At this point Ben achieved positive cash flow, and all seemed well. But then he started to encounter issues that typically arise when users begin to adopt the product, and the number of customization requests increases drastically, each one being individual. You may recognize the situation, especially if you develop B2B applications. In this area, customization requests are very common.

As time goes on, Ben's initial optimism gives way to frustration and burnout — an all-too-common reality in early-stage B2B development.

<img src="{{strapiUrl}}/uploads/Jmix_Delivery_Models_Unpacked_Article_rev6_html_848ae6a3_c86e5fab57.png" width="380" alt="Frustrated software engineer">

## What Went Wrong?

The answer is simple: at this stage, each minor logic fix has to be patched across 10 code forks, which leads to implementing 10 risky releases. What’s even worse, whenever Ben finds a bug in the core logic, he needs to fix it in every fork. It also becomes very hard to reuse features across the customer pool and to evolve the product itself. So, there is no room for growth, and all Ben’s time is now spent patching the forks rather than delivering new features to the product’s users.

Why do so many software engineers fall into this trap? Because by default, developers tend to start a new branch for every client. They arrange a dedicated database for each customer and then make changes in those branches, according to requests. As the infrastructure becomes more complex, they switch to fully manual deployment, which slows down progress and makes scaling much harder. We call this type of software development life cycle **“Copy, Paste and Pray”**.

It may seem trivial from the outside. But if you’ve experienced this situation firsthand, you know how stressful it can become. And this is exactly what we are going to explore below — how to avoid such pitfalls when starting your own digital product. This information is also useful for those who provide multi-client internal systems and are trying to balance customizations and maintainability.

To sum it up, Jmix is a perfect solution for Java/Kotlin teams who:
- Deliver multi-client, modular, or internal systems
- Work with limited or no frontend developers
- Need to balance customization with maintainability

These goals are achieved with the help of three delivery models that Jmix supports out of the box. Let's discuss each of them in detail.
<br>
<style type="text/css">
.tg  {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px; font-size:14px;
  overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-size:14px;
  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-bx42{border-color:#c0c0c0;text-align:left;vertical-align:top}
.tg .tg-29ir{background-color:#B4A7D6;border-color:#c0c0c0;text-align:left;vertical-align:top}
</style>
<table class="tg"><thead>
  <tr>
    <th class="tg-bx42">&nbsp;&nbsp;			 		</th>
    <th class="tg-29ir">Ideal for</th>
    <th class="tg-29ir">Solution<span style="background-color:#B4A7D6"> </span></th>
    <th class="tg-29ir">Benefits</th>
  </tr></thead>
<tbody>
  <tr>
    <td class="tg-29ir">Extension model</td>
    <td class="tg-bx42">Dev shops</td>
    <td class="tg-bx42">Core + Extension</td>
    <td class="tg-bx42">Reuse 		</td>
  </tr>
  <tr>
    <td class="tg-29ir">SaaS model</td>
    <td class="tg-bx42">Product teams 		</td>
    <td class="tg-bx42">Multitenant app</td>
    <td class="tg-bx42">Scaling 		</td>
  </tr>
  <tr>
    <td class="tg-29ir"> Self-hosted model</td>
    <td class="tg-bx42">Regulatory 		</td>
    <td class="tg-bx42">Composite project 		</td>
    <td class="tg-bx42">Control 		</td>
  </tr>
</tbody>
</table>

## Core Extension Model

If you're considering Jmix as the platform for your existing or next product, let’s begin with the [Core Extension Model](https://docs.jmix.io/jmix/modularity/index.html).

Jmix applications are built from subsystems—separate modules that encapsulate specific functionality. These can include domain logic, UI screens, roles, integrations, or reusable services. Subsystems are categorized as either core (provided by the Jmix platform, like security, data access, UI) or optional (added on demand, like Reports, BPM, or Multitenancy).

In Jmix terminology, subsystems are typically delivered as add-ons. An add-on is a self-contained functional unit that can be included in multiple projects. Developers can create custom add-ons to share business logic or integrations across teams or clients. The Core Extension Model builds on this modular structure.

You can implement this model in two ways:
1. **Reusable functionality as add-ons**: For example, you can create an add-on that retrieves national currency exchange rates. You can then integrate this into multiple projects. If the external API changes, you only update the add-on. All projects that depend on it get updated during the build process.
2. **Application core as an add-on**: You develop your core application as an add-on and deliver it to your clients. Each client can extend this core in their own application.

<img src="{{strapiUrl}}/uploads/Jmix_Delivery_Models_Unpacked_Article_rev6_html_f24ddccd_1d4f75b5e6.png" width="630" alt="For Client A, you extend this CRM with a Deals module, new UI screens, and custom roles. For Client B, you add a new approval flow and industry-specific dashboards.">

Let’s say you’ve built a niche CRM system - with shared entities, business logic, UI, and roles - and packaged it into a reusable core add-on. For Client A, you extend this CRM with a Deals module, new UI screens, and custom roles. For Client B, you add a new approval flow and industry-specific dashboards. Each client has their own Jmix project that depends on the same CRM core, but is extended in a modular and isolated way.

This setup allows you to:
- Deliver updates to the shared core and detect integration issues at compile time
- Keep client-specific logic separate and maintainable
- Delegate product customizations to partners or local teams using the same extension mechanisms

This approach is especially effective when you want to enable third-party developers or regional partners to adapt your product for local industries or compliance needs - without touching the core logic.

## SaaS Model

If your customers do not require many customizations and you aim to scale your application efficiently, consider the SaaS (Software as a Service) model. Jmix supports this model out of the box with a free [Multitenancy add-on](https://www.jmix.io/marketplace/multitenancy/).

![Jmix_Delivery_Models_Unpacked_Article_rev6_html_5a04f67c.png]({{strapiUrl}}/uploads/Jmix_Delivery_Models_Unpacked_Article_rev6_html_5a04f67c_dd7493d8c6.png)

In a multitenant model, all customers (tenants) access the same application instance. The Multitenancy add-on allows you to separate data, logic, roles, and permissions by tenant. You can:
- Use tenant-specific filters
- Create tenant-specific reports
- Define dynamic attributes per tenant
- Customize BPMN workflows per tenant

You can explore a demo of this setup via the [Jmix Bookstore application](https://demo.jmix.io/bookstore). For a real-world case, take a look at <a href="https://www.youtube.com/live/x73sa66RCcI?si=ZWRWaik6jNbHOW8o" target="_blank" rel="nofollow">Certikeeper</a> — a SaaS product built entirely with Jmix defaults and launched by a client team as their first product. Thanks to Jmix’s built-in multitenancy support, [Certikeeper](https://certikeeper.nl/) was delivered with minimal infrastructure and without excessive customization effort.

The SaaS model is ideal for SMB-targeted solutions with standardized workflows. But if you’re selling to banks, energy providers, or public institutions, the centralized infrastructure and limited customization options might not be acceptable.

## Self-Hosted & Composite Project Model

For clients in highly regulated industries — such as government, utilities, or banking — who demand full control, a **self-hosted** delivery model is often required. These customers may ask for complete source code access and expect the application to run in isolated environments, sometimes even offline.

In these scenarios, the product is delivered as a [composite project](https://docs.jmix.io/jmix/studio/composite-projects.html) — a Gradle-based setup where the main application includes multiple reusable or custom modules as local dependencies. This setup allows for:
- Building a dedicated client version from selected modules
- Customizing and extending features without duplicating the entire codebase
- Supporting long-term contracts with heavy integrations (e.g., ERP, CRM)

Jmix’s modular architecture allows teams to split functionality into bounded contexts — such as Inventory, Document Flow, or Delivery — and maintain them separately. You can keep a clean shared core and deliver only relevant modules per customer.

Composite builds are especially helpful when delivering code into a customer’s private Git repository. Customers can use Jmix Studio to assemble their own versions of the product, extend certain modules, and manage deployment themselves - all while still benefiting from updates to the core.

## Summary Matrix

<style type="text/css">
.tg  {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-size:14px;
  overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-size:14px;
  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-a0vl{background-color:#D9D2E9;border-color:#ffffff;font-weight:bold;text-align:left;vertical-align:top}
.tg .tg-cuar{background-color:#D9D2E9;border-color:#ffffff;font-weight:bold;text-align:center;vertical-align:top}
.tg .tg-xr1o{background-color:#351C75;border-color:#ffffff;font-weight:bold;text-align:left;vertical-align:top}
.tg .tg-xw6a{background-color:#351C75;border-color:#ffffff;font-weight:bold;text-align:center;vertical-align:top}
.tg .tg-5qbw{background-color:#B4A7D6;border-color:#ffffff;font-weight:bold;text-align:left;vertical-align:top}
.tg .tg-e6ze{background-color:#B4A7D6;border-color:#ffffff;font-weight:bold;text-align:center;vertical-align:top}
</style>
<table class="tg" style="undefined;table-layout: fixed;"><colgroup>
<col style="width: 173px">
<col style="width: 142px">
<col style="width: 229px">
<col style="width: 132px">
</colgroup>
<thead>
  <tr>
    <th class="tg-xr1o"> <span style="color:#FFF">Criteria</span></th>
    <th class="tg-xw6a"><span style="color:#FFF">Extension model</span></th>
    <th class="tg-xw6a"><span style="color:#FFF">SaaS model</span></th>
    <th class="tg-xw6a"><span style="color:#FFF">Self-hosted model</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td class="tg-5qbw">Multi-client scaling</td>
    <td class="tg-e6ze">✅✅</td>
    <td class="tg-e6ze"> 			✅✅✅<span style="background-color:#B4A7D6"> 		</span></td>
    <td class="tg-e6ze">✅</td>
  </tr>
  <tr>
    <td class="tg-a0vl">Per-client customization</td>
    <td class="tg-cuar">✅✅</td>
    <td class="tg-cuar"> 			✅<span style="background-color:#D9D2E9"> 		</span></td>
    <td class="tg-cuar">✅✅✅</td>
  </tr>
  <tr>
    <td class="tg-5qbw">Code reuse</td>
    <td class="tg-e6ze">✅✅</td>
    <td class="tg-e6ze"> 			✅✅✅<span style="background-color:#B4A7D6"> 		</span></td>
    <td class="tg-e6ze">✅</td>
  </tr>
  <tr>
    <td class="tg-a0vl">Design complexity</td>
    <td class="tg-cuar">$</td>
    <td class="tg-cuar"> 			$$<span style="background-color:#D9D2E9"> 		</span></td>
    <td class="tg-cuar">$$$</td>
  </tr>
  <tr>
    <td class="tg-5qbw">DevOps complexity</td>
    <td class="tg-e6ze">$$</td>
    <td class="tg-e6ze"> 			$$$<span style="background-color:#B4A7D6"> 		</span></td>
    <td class="tg-e6ze">$</td>
  </tr>
</tbody></table>

## Final Thoughts

The **Extension Model** offers a strong balance of maintainability and customization. It’s ideal when you don’t need massive scale but still need client-specific features.

The **SaaS Model** works best when your target audience doesn’t require heavy customization and shared infrastructure is acceptable.

The **Self-Hosted Model**, often combined with the composite project approach, fits regulated or high-control environments and enables modular customization while reducing code duplication.

If you’re not sure which model fits your case, [Jmix team](https://www.jmix.io/services-support/) can help with architecture design, deployment planning, or training to avoid common mistakes early in the process.

<img src="{{strapiUrl}}/uploads/Jmix_Delivery_Models_Unpacked_Article_rev6_html_16986cbc_af06db88ce.png" width="380" alt="Happy software engineer">

**Develop smart, not hard! With Jmix!**
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Seven Illusions of Low Code]]></title>
            <link>https://www.jmix.io/blog/seven-illusions-of-low-code</link>
            <guid>https://www.jmix.io/blog/seven-illusions-of-low-code</guid>
            <pubDate>Mon, 14 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Itog_fac80e800a.png">Everywhere you look, even the most serious enterprise solutions are expected to have at least some low-code elements. ]]></description>
            <content:encoded><![CDATA[Low code gatecrashed the corporate landscape in the 2020s, growing faster than anyone expected. At first, we thought, “Well, it’s a cute little thing—let the users play at being programmers as long as they don’t get in the way.” Fast forward to today, and everywhere you look, even the most serious enterprise solutions are expected to have at least some low-code elements. 
  
**But why?**
 
The hype really took off in 2021, when Gartner declared, “By 2024, 65% of all applications will be built using low-code technologies.” That stat spread like wildfire through every CIO chat group. 
 
It’s easy to see what fuelled the buzz: COVID hit; everyone suddenly needed to work remotely; IT teams were stretched thin, and people were plugging holes with whatever tools they could find. Low code appears to get the job done—you just throw something together quickly, launch it, and the business is happy. Nobody was really thinking about how they’d have to support, upgrade, and maintain all this stuff down the road. 
 
But here’s the thing: all the COVID-related fuss is long over, yet—according to Google Trends—interest in low code is still going strong. 

![235219cf914bfb003fc40f5230df81e5.png]({{strapiUrl}}/uploads/235219cf914bfb003fc40f5230df81e5_2f35c924d1.png)
*Source: Google Trends*

That’s odd, because it doesn’t really line up with what’s actually happening out there. The facts are that as follows: as of 2024, only 15% of enterprises are using low-code platforms for mission-critical applications—this is straight from Gartner themselves. Yet, in the same breath, they predict that by 2029, that number will skyrocket to 80%. Sure, we’ll believe it when we see it! (<a href="https://www.mendix.com/resources/gartner-magic-quadrant-for-low-code-application-platforms/" target="_blank" rel="nofollow">See source</a>.)

## How I Fell for Low Code (and Fell Out of Love)

 Don’t get me wrong—I have nothing against the idea of low code as such. In fact, there are plenty of cases where this approach really shines. Take batch scanning, for example: it’s a clear, well-defined tech process, which is practically made for low code automation. Remember Kofax? That was pretty much the perfect tool for batch document scanning. The workflow was hardwired: Preparation – Scan – Recognition – Validation – Verification – PDF Generation – Export. 

![1f28f776213b28f5d39c355ec3aa416a.jpg]({{strapiUrl}}/uploads/1f28f776213b28f5d39c355ec3aa416a_61ab35362d.jpg)

Everything was set up visually, and if you needed more, you could write a bit of script, something like Visual Basic. I once sold this solution to IKEA to digitize their paper financial archives, set it up myself, and supported it for a few years. This was around 2006—back when nobody had even heard the term “low code.” But that’s exactly what it was. And what about all the classic low-code pitfalls people run into today? I saw them all in that little project. 
 
It started with the business getting fed up with digging through piles of paper to find invoices or delivery notes from five years ago. As usual, IT had no resources for the project. So, we took the classic “guerrilla” approach to bringing low code into the organization—through a specific business need that IT couldn’t or wouldn’t help with. And, as often happens with low code, we got quick results—bam, it worked! And then we got a full serving of all the typical low-code headaches. 
 
First, the local IT team wanted nothing to do with supporting Kofax—some weird tool used by one department? No one was going to dedicate a specialist to figure it out. At least they didn’t ban it outright. Then, one day I show up—and everything they’d scanned over six months is gone. The drive with the archive just disappeared. I go to IT—they shrug their shoulders. “It’s not our system, not our problem.” Later they admitted they’d accidentally wiped it—it wasn’t their responsibility, after all. So, we scanned everything again. 
 
Of course, there was no documentation for the solution. As soon as the business saw the price tag for documenting, they cut that entry from the budget. At the time of setting it all up, that wasn’t a big deal—the product itself was well-documented, and I kept the configuration in my head. But a year or two later, I couldn’t remember what magic I’d created. If something broke—like when documents came in on different paper stock—I basically had to reconfigure everything from scratch. 
 
All that said, low code is a solid technology. It just needs to know its place. 

## Low-Code: A Cheeky Term 

Marketers were quick to spot the gap between what businesses wanted and what IT could deliver. In 2014, Forrester analysts gave this gap a catchy name: ‘low-code’— and promised that now anyone could build systems without programmers. Business leaders believed it, and for a while, it worked. 

But what’s really behind this promise? Low-code doesn’t eliminate programming—it just changes its shape. When you, for example, drag and drop a “Send Email” block, you’re simply calling a pre-written wrapper around an SMTP client. Everything’s already been done—just not by you. But as soon as you want to deviate from the standard scenario, you have to write your own code—not in a familiar IDE, but in some proprietary editor. 
 
Low-code hides complexity, but it doesn’t eliminate it. The architecture and behavior of your system are dictated by the platform. Simplicity comes at the cost of flexibility, and sometimes configuring is harder than traditional programming. The moment your requirements go beyond what the visual designer can handle, you end up fighting the platform instead of building your application. 
 
Still, some kind of aa miracle happened in the market: yesterday’s vendors of ECM, BPM, CRM systems, and 4GL languages suddenly rebranded themselves as low-code pioneers, and the market was flooded with a number of low-code platforms. Of course, nothing really has been changed inside—they just updated their slogans. 

## The Forefathers of Today’s Low-Code Platforms 
 
Technically, low-code is built on the same foundations as the tools of past decades: visual modelling, templates, configuration instead of programming, and a declarative approach. We’ve already seen all this in the RAD platforms of the 1990s, 4GL languages, ERP systems, and DSL frameworks. Even Excel with macros has features reminiscent of low-code. 
 
In other words, low-code is not a new technology. It’s a new packaging of an old idea. Here are a few examples to illustrate the point:

- **VisualAge** was a series of visual development environments from IBM in the 1990s that allowed users to build applications by dragging and dropping components and generating code—long before the modern low-code platforms appeared on the scene. The most famous version, VisualAge for Java, later became the foundation for the Eclipse IDE. Although VisualAge was ahead of its time with its visual programming concept, it was too heavyweight and developer-oriented to become a truly mainstream solution. 
- **Visual Basic** appeared in 1991 as a rapid application development (RAD) tool from Microsoft. The word “visual” in its name highlights the platform’s key feature—visual design of user interfaces by dragging and dropping elements (buttons, input fields, lists) directly onto a form, which greatly simplified UI creation compared to traditional programming. Despite the convenience of visual design, Visual Basic is not a low-code platform in the modern sense, since implementing business logic and application interaction still required writing code in the Visual Basic language. 
- **PowerBuilder** is one of the veterans of the rapid business application development world, born in the early 1990s at Sybase and long considered a dream tool for corporate developers. It was a powerful visual form builder with its own scripting language, enabling the creation of complex client-server applications much faster than coding everything from scratch. PowerBuilder is still alive and supported today though in the era of clouds and low-code platforms, it’s no longer at the cutting edge, but for many organizations, it remains a reliable workhorse with a rich history. 

![381844a417e9b6d75cd66f6d86d31f4d.png]({{strapiUrl}}/uploads/381844a417e9b6d75cd66f6d86d31f4d_21f1539f6a.png)
*This image was generated by ChatGPT, but boxes look almost real! That’s pretty much how I remember them. By the way, I still have a VisualAge box lying around at home—a leftover from old stock. It’s a real collector’s item now!*

As we can see, the history of low-code began long before the term itself appeared. VisualAge, Visual Basic, PowerBuilder—all of them, in their own way, aimed at simplifying development, hiding routine tasks behind visual tools, and shortening the time to a finished product. But each had its limits: as soon as you faced non-standard requirements, the developer still had to “look under the hood.” 
 
Today’s low-code platforms have inherited that same duality: the promise of simplicity—and the hidden complexity that emerges at the next level. The only real difference is that now, the old idea is wrapped in a modern marketing facade and a whole methodology of digital transformation. New terms, old mechanisms—and the same old problems. 

## What if you go completely code-free?

Following the rise of low-code, a new wave emerged—*no-code*, as a more radical version of the same idea. In essence, it’s the same approach, just taken to the extreme: absolutely no code, not even a hint of programming. Just a mouse, ready-made blocks, a visual editor, and the dream that now the business can build whatever it needs on its own. 

The idea sounds appealing: any employee can assemble a working application, automate a process, or create a simple CRM. The reality, as usual, is different. As long as the task is simple and straightforward—like building a landing page in **Tilda**, creating a survey in **Typeform**, or setting up an integration in **Zapier**—everything works. But as soon as the business process goes beyond the capabilities of the builder, the real challenge begins: missing APIs, insufficient logic, lack of validation, and so on. Most importantly, there is no real understanding of how things actually work. 
No-code creates the illusion of independence from developers. But rather than making developers unnecessary, you simply end up needing them later—often to fix, rewrite, or integrate whatever was quickly assembled. Instead of removing technical debt, no-code solutions quietly allow it to build up behind the scenes. 
 
Low-code is at least honest: you have to code anyway, but a little. No-code promises that you won’t need any at all. But they forget to mention that you won’t need code only until you want something real: scalability, version control, testing, complex logic, security. 
 
Fortunately, businesses haven’t fallen for this trap, and no-code hasn’t found a place under the corporate sun. Its niche is quick-and-dirty solutions that don’t aim for anything serious—building a small website, automating a simple process for a small business, and so on. In short, you can forget about no-code if we’re talking about serious systems. 

## The Less Code Paradox

I don’t think I’ll surprise anyone by saying that most developers can’t stand low-code and everything associated with it. What’s especially ironic is that these same developers love tools that save them from repetitive tasks and boilerplate code, and they eagerly use high-level abstractions to write less code by hand. 
 
Still, the amount of code in large projects doesn’t actually decrease—after all, you can’t describe complex things in just a few lines. What has changed is that developers no longer have to spend time on monotonous work: libraries, smart IDEs, frameworks, and now AI assistants take care of the routine, letting developers focus on truly interesting problems. But I’ll talk more about AI capabilities another time. 
 
Take **Lombok**, for example—isn’t it low-code? A few annotations replace the tedious typing of constructors, getters, setters, and other boilerplate stuff that your code simply can’t run without. Lombok saves hundreds of lines and hours of work, and it does so at the language level, while remaining transparent to the developer. **IntelliJ IDEA** offers something similar, letting you generate all that boilerplate with just a couple of clicks—which is great, because it gives developers a choice. 
 
And what about the mighty **Spring** framework? It truly encapsulates complexity and takes over bean management, but in return it offers developers clear rules and a rich set of features. It says, “I’ll set up the environment for you, connect the necessary components, and handle transactions—just describe what you need, not how it should work under the hood.” 

![63c9a404bcbfd04e3db089a49635b486.png]({{strapiUrl}}/uploads/63c9a404bcbfd04e3db089a49635b486_cff2af53cb.png)

So, modern tools are all about helping developers write less code and think more. In fact, these tools should have rightfully been called “low-code”, but the term was already taken. As a workaround, the term “less code” was coined—not as catchy or transparent, but at least honest. Less code is about saving effort without pretending that code is no longer needed. It’s about raising the level of abstraction, automating routine tasks, and focusing on expressiveness. Developers still write code, but they do it faster, cleaner, and with the help of powerful tools: DSLs, templates, generators, annotations, smart IDEs, and so on. 
 
The fundamental difference between low-code and less code is this: with low-code, you really do write very little code, but everything else is a “black box”—platform components you can’t inspect or modify. With less code, everything is code, whether written by hand or generated by tools. Even the framework itself is code, you can read and modify it if necessary. 
 
After that, you compile and run your application, just like you would with a simple “Hello, world!” In contrast, a low-code application runs in its own runtime environment, which you also don’t control. 
 
So, unlike low-code, less code doesn’t promise that anyone can “build an app in an evening.” It simply says: you’re still a programmer, but you’ll save time on repetitive tasks. And that’s an honest deal—no misleading promises, no loss of control. 
 
The irony is that real progress in software development is happening along the path of less code, not low-code. But the market loves flashy names, and “low-code” sounds more revolutionary. In reality, though, it’s more about rebranding than real change. 

## Conclusion

Low-code is neither evil nor a panacea. It’s a tool—a good one, in the right hands and with the right expectations. The problem isn’t that it exists, but that it’s been credited with too much: simplicity, universality, speed, independence, even a kind of revolutionary potential. But these are all marketing illusions: 
### 1. The Illusion of Simplicity   
Low-code seems simple—until you step outside the boundaries of its visual tools. The complexity doesn’t disappear; it just goes into hiding. But it always comes back, often with a vengeance. Yes, low-code lowers the barrier to entry, that’s true. But sooner or later, you’ll still have to dive deep into the proprietary product. 
### 2. The Illusion of “Citizen Developers”   
Low-code promises that anyone can succeed—that any specialist can become a citizen developer. In reality, professional developers still get involved: maybe later, but always on call. They come in to sort things out, fix, or rewrite. In theory, you could set up a division of labour between citizen and professional developers, but in practice, this is rare. 
### 3. The Illusion of Speed   
Low-code claims that everything can be done quickly. That’s true if your scenario is standard. But for non-standard tasks, things get complicated: configurations, platform limitations—all of this eats up time. Think ahead about where low-code is applicable, so you don’t get stuck in a project forever. 
### 4. The Illusion of Low Cost   
Low-code lures you in with a low-price tag, but that works only at the beginning. The real cost for an enterprise project can be quite substantial. Licenses, customization, integrations, and training quickly turn “cheap” into “not at all.” Make sure to estimate the total cost of ownership before jumping into a low-code solution. 
### 5. The Illusion of Universality   
Low-code claims to be suitable for every situation. Actually, it is not. This technology is great for automating simple processes or building prototypes. But using it as the core of a corporate system is a recipe for disaster. 
### 6. The Illusion of Simplified Maintenance   
Low-code offers its own deployment and delivery tools. That’s great—until you need to integrate everything into your corporate DevOps pipeline. That’s when the real fun begins. Mature platforms partially solve this problem, but the cost of integrating with DevOps remains high. 
### 7. The Illusion of Revolution   
Low-code arrives as a cutting-edge technology. In truth, it’s an old idea with a new name. RAD, 4GL, visual builders—all of this has been around before. Low-code just has better marketing. 
 
Therefore, the main advice is this: **don’t be tempted by illusions**. Use **low-code** where it truly makes sense. But when reliability, scale, and flexibility are required, it’s better to stick with professional **less code** tools. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Beyond React: a comparative analysis of React and Jmix for writing UI business applications ]]></title>
            <link>https://www.jmix.io/blog/beyond-react-a-comparative-analysis-of-react-and-jmix-for-writing-ui-business-applications</link>
            <guid>https://www.jmix.io/blog/beyond-react-a-comparative-analysis-of-react-and-jmix-for-writing-ui-business-applications</guid>
            <pubDate>Wed, 09 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_vs_React_1_7f6af51e85.png">Modern frameworks like React enable the efficient creation of visually appealing and functional interfaces. But is React the only option? What other tools can effectively support business application development.]]></description>
            <content:encoded><![CDATA[## Introduction 

Historically, enterprise software development centered on desktop applications with utilitarian user interfaces—dominated by tables, buttons, forms, and multiple pop-up layers. Businesses were typically cautious about change, especially when it involved added costs, making aesthetically pleasing UIs rare in business applications. 

Today, modern frameworks like React enable the efficient creation of visually appealing and functional interfaces. But is React the only option? What other tools can effectively support business application development? 

## Key Requirements for Business Interfaces 

To begin with, consider reviewing a typical business interface using the example of an application from [SAPUI5 Demo](https://sapui5.hana.ondemand.com/test-resources/sap/m/demokit/orderbrowser/webapp/test/mockServer.html?sap-ui-theme=sap_horizon_dark#/Orders/7311/?tab=shipping): 

![1.jpg]({{strapiUrl}}/uploads/1_864ddc3cce.jpg)

While this looks rather utilitarian, critically, it fulfills its purpose. The interface shows all available orders, with detailed information, and provides filtering options. However, the UI could definitely be improved. The spacing and alignment of the recipient’s card are unclear, the splitter is misaligned, the search control buttons are different sizes, and so on. 

In practice, no one will fix this, because, in an enterprise application, visual polishing is never a top priority. Users don’t expect to be spoiled by high-end aesthetics, and so most developer time will be spent fulfilling “what it does” requirements, rather than “how it looks”. 

Even from this small example, we can identify several areas to focus upon: 

1. More Data = More Screens. A typical business application may have more than 50 different entities in its database. Therefore, multiple screens are necessary to manage these entities. Even with basic CRUD operations for each entity, you will end up around 100 similar screens (one view screen and one edit screen for each). 

2. Functionality.  Ideally, every business user would experience the same level of functionality that they enjoy with Excel. But this is impractical with web technologies. To bring users closer to this ideal, developers have included various data interactions tools such as filters, logical grouping, sorting, and the ability to modify the table structure in the interface. However, these tools can clutter the interface, making it harder to focus on the main task at hand. 

3. Security. It’s not uncommon for enterprise application developers to spend up to 40% of their project time configuring access rights. Why is this the case? Well, even the most basic business app requires at least two roles: a system user and a system administrator. In reality this is often expanded to department heads, several managers, and a support specialist who also needs access to certain screens. If only the support specialist and department head need access to a particular screen, you’re already looking at more than six roles. All of these different roles must be taken into account when designing the UI. This makes it challenging to assemble all of the necessary UI elements for each role. 

4. Cheaper Means Better. The primary goal of any business is to maximize profits and complete projects within budget, which requires minimizing expenses. Therefore, extra budget is usually not allocated for aesthetics, especially when it comes to internal business systems. 

## Technologies 

Now that we’ve discussed the requirements, let’s take a look at the technologies that best suit them. 

The backend is relatively simple. Typically, it can be implemented using Python with Django or Java with Spring Boot. However, for large-scale enterprise solutions, Java has become the de-facto standard for backend development, so let’s focus on that approach. 

Choosing a frontend technology, on the other hand, is a much more complex process. We need to find something that is cost-effective (refer to point 4) and visually appealing. Popularity and trends in this area are constantly changing, but some of the standard options include React, Next, Angular and Vue. We will choose the most popular and flexible option among these – React. 

With the foundation laid, it’s time to define our opponent. The chosen technologies will be compared to Jmix, a ready-to-use solution that has been tailored to meet the requirements we have outlined for enterprise applications. Jmix is a full-stack Java framework designed to build enterprise applications. 

For the comparison, we’ll use implementations of a standard Petclinic CRUD application built with Jmix and React + Spring Boot respectively. 

## About the Architecture 

In this comparison, we are looking at a widely recognized standard and a niche solution. The difference begins at the application architecture level. A web-application built with the Java Spring + React has a straightforward structure. 

- Building the Backend 
  - Entities 
  - Repositories for entities 
  - Services to work with the entities 
  - Validators 
  - DTOs for entities 
  - Mappers 
  - REST-controllers 
- Building the Frontend 
  - Components for editing and viewing lists of entities 
  - API requests and binding data to components 
  - Setting up routing within the application 
  - Configuring validation for UI components and filters 
  - Styling 

With Jmix, things become quite interesting. It is a full-stack solution with a backend based on Spring Boot. The UI is built using the Vaadin Flow framework, which might come as a surprise at first.  

Vaadin uses the server-side rendering method, where the server maintains the state of the entire interface. It is a web framework built on the Web Components specification and the Google Polymer library. The server-side of Vaadin is written in Java, so in Jmix, the backend and frontend are both written in the same language - Java. 

![2.jpg]({{strapiUrl}}/uploads/2_98fccb1efa.jpg)

With this approach, there is no way for the UI state to change without the server eventually learning about it through a synchronization request. This solves many security issues. To create reusable components, Vaadin uses the concept of custom elements, which is similar to the component concept in React. You can also use JavaScript and TypeScript to create custom web components. 

## Start a Project 

To start a project using native React, you’ll need to use the create-react-app tool which will help you set up the project structure. You’ll also need to configure Webpack, install the necessary npm modules and, for Spring Boot projects, use Spring Initializr to generate applications and define application properties. Finally, you can set up Spring configuration as needed. 

Here is where Jmix starts to show its advantages as a full-stack development framework. Jmix offers a predefined set of templates and extensions. The standard template creates a full-stack application with a basic user entity, screens for editing, and a role management system. Naturally, these types of templates limit customization options, something to be aware of. 

![3.jpg]({{strapiUrl}}/uploads/3_aac1d07aca.jpg)

## Creating Screens 

Let’s take a look at the ‘Pets’ screen in the React application. To create this interface, we needed to write some basic layout, fetch data from a backend using a REST API, map the data into a table row component, and then render it on the page. 

![4.jpg]({{strapiUrl}}/uploads/4_3f76a8a833.jpg)

```  
 // ...some boilerplate code above 
 
    render() { 
        const { pets, isLoading } = this.state; 
 
        if (isLoading) { 
            return <p>Loading...</p>; 
        } 
 
        const petList = pets.map((pet) => { 
            return ( 
                <tr key={pet.id}> 
                    <td>{pet.name}</td> 
                    <td>{pet.birthDate}</td> 
                    <td>{pet.type?.name}</td> 
                    <td>{pet.owner.user.username}</td> 
                    <td> 
                        <Button size="sm" color="info" tag={Link} 
                            to={`/pets/${pet.id}/visits`}> 
                            Visits 
                        </Button> 
                    </td> 
                    <td> 
                        <ButtonGroup> 
                            <Button size="sm" color="primary" tag={Link} 
                                to={"/pets/" + pet.id}> 
                                Edit 
                            </Button> 
                            <Button size="sm" color="danger" onClick={() => this.remove(pet.id)}> 
                                Delete 
                            </Button> 
                        </ButtonGroup> 
                    </td> 
                </tr> 
            ); 
        }); 
 
        return ( 
            <div> 
                {/* <AppNavbar /> */} 
                <Container style={{ marginTop: "15px" }} fluid> 
                    <h1 className="text-center">Pets</h1> 
                    <Button color="success" tag={Link} to="/pets/new"> 
                        Add Pet 
                    </Button> 
                    <Table className="mt-4"> 
                        <thead> 
                            <tr> 
                                <th>Name</th> 
                                <th>Birth Date</th> 
                                <th>Type</th> 
                                <th>Owner</th> 
                                <th>Visits</th> 
                                <th>Actions</th> 
                            </tr> 
                        </thead> 
                        <tbody>{petList}</tbody> 
                    </Table> 
                </Container> 
            </div> 
        ); 
    } 
```
This is a basic implementation with inline editing buttons. This approach was chosen to avoid the need for implementing row selection functionality. There are also simple buttons that simply redirect to the corresponding pet creation/editing screens. The Remove button has a ‘delete’ function, which we will discuss later. 

Now let’s take a look at the same screen in Jmix. Jmix has a built-in screen generator for creating CRUD screens for entities. This generator uses predefined templates to populate the screen with the necessary columns and form fields based on the entity data. All the components used are based on the Vaadin Flow library. 

![5.jpg]({{strapiUrl}}/uploads/5_25fafddb86.jpg)

What does it take to create a screen like this in Jmix? 

A screen in Jmix is defined using a controller and an optional descriptor. This controller is a Java class that represents the UI screen. The descriptor is an XML file that defines the layout of the screen, making the code more concise and easier to read. The generator automatically creates both the controller and the descriptor for each screen. 

If you need to create screens for more than 12 entities, having a generator like this is much more convenient than manually creating each layout. 

```
 <layout> 
        <hbox width="100%" alignItems="BASELINE" classNames="buttons-panel"> 
            <propertyFilter 
                    id="identificationNumberFilter" 
                    property="identificationNumber" 
                    operation="CONTAINS" 
                    dataLoader="petsDl" 
                    labelPosition="TOP" 
                    label="msg://io.jmix.petclinic.entity.pet/Pet.identificationNumber" 
            /> 
            <propertyFilter 
                    id="typeFilter" 
                    property="type" 
                    operation="EQUAL" 
                    dataLoader="petsDl" 
                    labelPosition="TOP" 
                    label="msg://io.jmix.petclinic.entity.pet/Pet.type" 
            /> 
            <propertyFilter 
                    id="ownerFilter" 
                    property="owner" 
                    operation="EQUAL" 
                    dataLoader="petsDl" 
                    labelPosition="TOP" 
                    label="msg://io.jmix.petclinic.entity.pet/Pet.owner"> 
 
                <entityComboBox metaClass="petclinic_Owner" itemsContainer="ownersDc" /> 
            </propertyFilter> 
            <button id="clearFilterBtn" action="clearFilterAction" /> 
        </hbox> 
        <genericFilter id="genericFilter" 
                       dataLoader="petsDl" opened="false" summaryText="Advanced Filter"> 
            <properties include=".*"/> 
        </genericFilter> 
        <hbox id="buttonsPanel" classNames="buttons-panel"> 
            <button id="createBtn" action="petsDataGrid.create"/> 
            <button id="editBtn" action="petsDataGrid.edit"/> 
            <button id="removeBtn" action="petsDataGrid.remove"/> 
            <button id="excelExportBtn" action="petsDataGrid.excelExport"/> 
            <simplePagination id="pagination" dataLoader="petsDl"/> 
        </hbox> 
        <dataGrid id="petsDataGrid" 
                  width="100%" 
                  minHeight="20em" 
                  dataContainer="petsDc"> 
            <actions> 
                <action id="create" type="list_create"/> 
                <action id="edit" type="list_edit"/> 
                <action id="remove" type="list_remove"/> 
                <action id="excelExport" type="grdexp_excelExport"/> 
            </actions> 
            <columns> 
                <column property="name"/> 
                <column property="identificationNumber"/> 
                <column property="birthdate"/> 
                <column property="type"/> 
                <column property="owner"/> 
            </columns> 
        </dataGrid> 
        <hbox id="lookupActions" visible="false"> 
            <button id="selectBtn" action="selectAction"/> 
            <button id="discardBtn" action="discardAction"/> 
        </hbox> 
    </layout> 
```
In the generated code, you can find declarative definitions for the table, its actions, the buttons above it, and various filters. Overall, this is sufficient to make the screen fully functional. The framework provides all standard entity operation out-of-the-box. 

## Woking with Data 

To retrieve data from a server in a React application, you need to send a REST request. For example, on the “Pet” screen described earlier, this is how it works: 
```
    componentDidMount() { 
        fetch("/api/v1/pets", { 
            headers: { 
                "Authorization": `Bearer ${this.jwt}`, 
                "Content-Type": "application/json", 
            }, 
        }).then((response) => response.json()) 
            .then((data) => this.setState({ pets: data })); 
    } 
```
When the screen loads, a single request is sent to the server. 

Let’s now examine what happens when you click the Remove button. To delete data, another request must be sent to the server. 

```
  async remove(id) { 
        await fetch(`/api/v1/pets/${id}`, { 
            method: "DELETE", 
            headers: { 
                "Authorization": `Bearer ${this.jwt}`, 
                Accept: "application/json", 
                "Content-Type": "application/json", 
            }, 
        }).then((response) => { 
            if (response.status === 200) { 
                let updatedPets = [...this.state.pets].filter((i) => i.id !== id); 
                this.setState({ pets: updatedPets }); 
            } 
            return response.json(); 
        }).then(function (data) { 
            alert(data.message); 
        }); 
    } 
```
Overall, this is not too difficult, but it does require a fair amount of coding, especially when you take into account the backend request handling. 

In Jmix, data loading is managed using the dedicated data section within the same screen definition. It utilizes built-in mechanisms to retrieve data directly from a database. 

```
 <data readOnly="true"> 
        <collection id="petsDc" 
                    class="io.jmix.petclinic.entity.pet.Pet"> 
            <fetchPlan extends="_base"> 
                <property name="type" fetchPlan="_instance_name"/> 
                <property name="owner" fetchPlan="_instance_name"/> 
            </fetchPlan> 
            <loader id="petsDl"> 
                <query> 
                    <![CDATA[select e from petclinic_Pet e]]]]><![CDATA[> 
                </query> 
            </loader> 
        </collection> 
        <collection id="ownersDc" 
                    class="io.jmix.petclinic.entity.owner.Owner"> 
            <fetchPlan extends="_base"/> 
            <loader id="ownersDl"> 
                <query> 
                    <![CDATA[select e from petclinic_Owner e]]]]><![CDATA[> 
                </query> 
            </loader> 
        </collection> 
    </data> 
    <!-- layout -->
```
A JPQL query is defined directly in the XML code, specifying how data should be retrieved from the database. If you need to handle UI component events, you can do so in the controller by writing Java code. 

```
@Route(value = "pets", layout = MainView.class) 
@ViewController("petclinic_Pet.list") 
@ViewDescriptor("pet-list-view.xml") 
@LookupComponent("petsDataGrid") 
@DialogMode(width = "50em") 
public class PetListView extends StandardListView<Pet> { 
 
    @ViewComponent 
    private PropertyFilter identificationNumberFilter; 
     
    @ViewComponent 
    private PropertyFilter typeFilter; 
     
    @ViewComponent 
    private PropertyFilter ownerFilter; 
 
    @Subscribe("clearFilterAction") 
    public void onClearFilterAction(final ActionPerformedEvent event) { 
        identificationNumberFilter.clear(); 
        typeFilter.clear(); 
        ownerFilter.clear(); 
    } 
} 
```

The main difference between React and Jmix is that we work on the backend. When a button is clicked, we can directly call a service, perform additional data processing, or interact with a database. 

Layouts are written in XML and screen controllers in Java… At first glance, this might seem similar to Spring MVC, but there are some key differences. Here’s a comparison table: 
<br>
<style type="text/css">
.tg  {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-1wig{font-weight:bold;text-align:left;vertical-align:top}
.tg .tg-73oq{border-color:#000000;text-align:left;vertical-align:top}
.tg .tg-0lax{text-align:left;vertical-align:top}
</style>
<table class="tg"><thead>
  <tr>
    <th class="tg-73oq"> </th>
    <th class="tg-1wig">Jmix UI </th>
    <th class="tg-1wig">Spring MVC </th>
  </tr></thead>
<tbody>
  <tr>
    <td class="tg-0lax">Layout technology </td>
    <td class="tg-0lax">Proprietary layout system using declarative UI components in XML </td>
    <td class="tg-0lax">HTML templating engines (Thymeleaf, Freemarker, etc.) </td>
  </tr>
  <tr>
    <td class="tg-0lax">Client-side communication </td>
    <td class="tg-0lax">JSON used to configure web components </td>
    <td class="tg-0lax">Static HTML delivery </td>
  </tr>
  <tr>
    <td class="tg-0lax">Navigation technology </td>
    <td class="tg-0lax">Vaadin Flow React Router </td>
    <td class="tg-0lax">Mapping of HTTP requests to controllers </td>
  </tr>
</tbody>
</table>
<br>
Speaking of navigation, let’s move on to how it’s implemented in React and Jmix. 

## Creating Routing 

So, we have screens in our application and data is being loaded. Let’s examine how we navigate between these screens. 

In the React application, a simple Navbar component is implemented as a horizontal menu at the top of the page. 

```
  return ( 
    <div> 
      <ErrorBoundary FallbackComponent={ErrorFallback} > 
        <AppNavbar /> 
        <Routes> 
          <Route path="/" exact={true} element={<Home />} /> 
          <Route path="/plans" element={<PlanList />} /> 
          <Route path="/docs" element={<SwaggerDocs />} /> 
          {publicRoutes} 
          {userRoutes} 
          {adminRoutes} 
          {ownerRoutes} 
          {vetRoutes} 
        </Routes> 
      </ErrorBoundary> 
    </div> 
  ); 
```
To display routes based on a user’s role, you will need to define separate routes for each role. 

```
 roles.forEach((role) => { 
    if (role === "ADMIN") { 
      adminRoutes = ( 
        <> 
          <Route path="/users" exact={true} element={<PrivateRoute><UserListAdmin /></PrivateRoute>} /> 
          <Route path="/users/:username" exact={true} element={<PrivateRoute><UserEditAdmin /></PrivateRoute>} /> 
          <Route path="/owners" exact={true} element={<PrivateRoute><OwnerListAdmin /></PrivateRoute>} /> 
          <Route path="/owners/:id" exact={true} element={<PrivateRoute><OwnerEditAdmin /></PrivateRoute>} /> 
          <Route path="/clinics" exact={true} element={<PrivateRoute><ClinicListAdmin /></PrivateRoute>} /> 
          <Route path="/clinics/:id" exact={true} element={<PrivateRoute><ClinicEditAdmin /></PrivateRoute>} /> 
          <Route path="/clinicOwners" exact={true} element={<PrivateRoute><ClinicOwnerListAdmin /></PrivateRoute>} /> 
          <Route path="/clinicOwners/:id" exact={true} element={<PrivateRoute><ClinicOwnerEditAdmin /></PrivateRoute>} /> 
          <Route path="/pets" exact={true} element={<PrivateRoute><PetListAdmin /></PrivateRoute>} /> 
          <Route path="/pets/:id" exact={true} element={<PrivateRoute><PetEditAdmin /></PrivateRoute>} /> 
          <Route path="/pets/:petId/visits" exact={true} element={<PrivateRoute><VisitListAdmin /></PrivateRoute>} /> 
          <Route path="/pets/:petId/visits/:visitId" exact={true} element={<PrivateRoute><VisitEditAdmin /></PrivateRoute>} /> 
          <Route path="/vets" exact={true} element={<PrivateRoute><VetListAdmin /></PrivateRoute>} /> 
          <Route path="/vets/:id" exact={true} element={<PrivateRoute><VetEditAdmin /></PrivateRoute>} /> 
          <Route path="/vets/specialties" exact={true} element={<PrivateRoute><SpecialtyListAdmin /></PrivateRoute>} /> 
          <Route path="/vets/specialties/:specialtyId" exact={true} element={<PrivateRoute><SpecialtyEditAdmin /></PrivateRoute>} /> 
          <Route path="/consultations" exact={true} element={<PrivateRoute><ConsultationListAdmin /></PrivateRoute>} /> 
          <Route path="/consultations/:consultationId" exact={true} element={<PrivateRoute><ConsultationEditAdmin /></PrivateRoute>} /> 
          <Route path="/consultations/:consultationId/tickets" exact={true} element={<PrivateRoute><TicketListAdmin /></PrivateRoute>} /> 
        </>) 
    } 
     
    // etc. 
} 
```
In Jmix, the role system is designed so that each role contains information about which screens the user can access. Roles are defined using annotated interfaces. For example, here’s how the Nurse role is defined. 

```
@ResourceRole(name = "Nurse", code = NurseRole.CODE) 
public interface NurseRole { 
 
    String CODE = "Nurse"; 
 
    // ... other policies 
 
    @ViewPolicy(viewIds = {"petclinic_MyVisits", 
            "petclinic_Pet.list", "petclinic_Pet.detail", 
            "petclinic_Owner.list", "petclinic_Owner.detail", 
            "petclinic_Visit.list", "petclinic_Visit.detail", 
            "petclinic_Specialty.list", "petclinic_Specialty.detail", 
            "petclinic_Veterinarian.list", "petclinic_Veterinarian.detail", 
            "petclinic_PetType.list", "petclinic_PetType.detail", "petclinic_PetType.lookup",}) 
    void views(); 
 
    @MenuPolicy(menuIds = {"petclinic_MyVisits", 
            "petclinic_Pet.list", 
            "petclinic_Owner.list", 
            "petclinic_Visit.list", 
            "petclinic_Specialty.list", 
            "petclinic_Veterinarian.list", 
            "petclinic_PetType.list"}) 
    void screens(); 
} 
```

This interface uses special annotations (policies) to control access to different parts of the application 

- The @MenuPolicy annotation is used to grant permission to display certain menu items. This allows users to see and interface with specific menu options. 
- Similarly, the @ViewPolicy annotation controls access to different screens or views within the application. It determines which screens a user can access based on their permissions. 

There are also policies related to entity access, but they are not the main focus of this comparison. 

In addition, it is possible to create roles within the running application. This allows not only developers, but also system administrators, to define roles and manage access to different parts of the system. 

Routing in Jmix is defined using the @Route annotation on screen controllers. These routes support both routeParameters (e.g., an entity ID in an editor screen) and queryParameters (custom screen state options). 

To define the menu structure and screen order, you can use a special XML file: 

```
<menu-config xmlns="http://jmix.io/schema/flowui/menu"> 
 
    <item view="petclinic_MyVisits" title="msg://io.jmix.petclinic.view.visit/myVisitsView.title" icon="CLIPBOARD_USER"/> 
    <menu opened="true" id="petclinic" title="msg://io.jmix.petclinic/menu.petclinic.title" icon="CLIPBOARD_PULSE"> 
        <item view="petclinic_Pet.list" title="msg://io.jmix.petclinic.view.pet.pet/petListView.title"/> 
        <item view="petclinic_Owner.list" title="msg://io.jmix.petclinic.view.owner/ownerListView.title"/> 
        <item view="petclinic_Visit.list" title="msg://io.jmix.petclinic.view.visit/visitListView.title"/> 
    </menu> 
    <menu id="application-masterdata" title="msg://io.jmix.petclinic/menu.application-masterdata.title" icon="ARCHIVE"> 
        <item view="petclinic_Specialty.list" 
              title="msg://io.jmix.petclinic.view.veterinarian.specialty/specialtyListView.title"/> 
        <item view="petclinic_Veterinarian.list" 
              title="msg://io.jmix.petclinic.view.veterinarian.veterinarian/veterinarianListView.title"/> 
        <item view="petclinic_PetType.list" title="msg://io.jmix.petclinic.view.pet.pettype/petTypeListView.title"/> 
    </menu> 
    <menu id="security" title="msg://io.jmix.petclinic/menu.security.title" icon="KEY_O"> 
        <item view="User.list" title="msg://io.jmix.petclinic.view.user/UserListView.title"/> 
        <item view="sec_ResourceRoleModel.list" 
              title="msg://io.jmix.securityflowui.view.resourcerole/resourceRoleModelListView.menu"/> 
        <item view="sec_RowLevelRoleModel.list" 
              title="msg://io.jmix.securityflowui.view.rowlevelrole/rowLevelRoleModelListView.menu"/> 
    </menu> 
    <menu id="datatools" title="msg://io.jmix.petclinic/menu.datatools.title" icon="DATABASE"> 
        <item view="datatl_entityInspectorListView" 
              title="msg://io.jmix.datatoolsflowui.view.entityinspector/listTitle"/> 
    </menu> 
</menu-config> 
```
You don’t need to specify which screens are available for each role separately – just define the entire menu, and Jmix will filter it based on the user’s access permissions. 

Here’s what the menu would look like for a user with the Nurse role: 

<img src="{{strapiUrl}}/uploads/6_c09158ffce.jpg" width="400">

As shown, the security and datatools sections from the menu.xml file is missing. These sections have been automatically filtered out by the built-in security system. 

## Obvious Drawbacks 

### Customization and Flexibility 

When relying on predefined components and approaches, customization options may be limited. You are forced to follow a path envisioned by the developers of the framework. However, with React, this is not a problem – it gives you the freedom to create any interface, regardless of its complexity or functionality. 

Although there is an option to style the application using CSS, the web components template is fixed. This means that you can’t simply add additional functionality to, for example, a table – you will either need to modify the existing web component or create a new one. 

If you wish to integrate a JavaScript library with a visual component, it’s important to understand that both server-side and client-side code will need to be written. This means that you can’t simply “plug in” the JS component as it is; instead, you’ll need to integrate it into your project’s infrastructure. This process can be time-consuming and requires substantial effort, as it involves customizing the library to suit your specific needs. 

### Scalability 

Since Jmix uses a server-side UI approach, it naturally requires more resources, especially server-side. When a user session is created, an instance of the UI is created on the server and occupies memory. As a result, you need to have a precise understanding of the number of concurrent users in order to provide enough computing resources. 

### Session Replication 

In addition, storing both the UI state and the session on the server presents challenges related to sessions replication. 

First, in order for replication to work, all UI states must be serializable. While all standard Vaadin components are serialized by default, it is not guaranteed that a custom visual component will also be serialized. 

Second, remember that we’re in the world of Java. A session is a Java object – a potentially large one – with many references to other Java objects. This can easily increase the size of the session to several megabytes. 

Third, every client request to a Jmix application modifies the session state to some extent. Event in simple cases where no application-level data is changed, synchronization points update their state. This means it’s crucial that multiple requests for the same session are never processed in parallel. 

All of this leads to a situation where standard session replication solutions don’t work well with Vaadin and Jmix. The only viable option is sticky sessions, which is not always convenient. This is one of the main drawbacks of the Vaadin framework. 

### Community 

React has one of the largest communities in the world of frontend development. There are a vast number of pre-build solutions, questions answered on forums, and documented workarounds – often at the top of Google’s search results. 

Obviously, the Jmix developer community is smaller compared to React, but it is active, vibrant and fast-growing. There is a dedicated forum where developers and users can find extensive support from each other. Additionally, a growing number of educational materials and demo applications are available. 

## Conclusion 

It seems that in certain cases, using React for building business applications may be overkill. At the very least, you’ll need two specialists – each responsible for their own part of the project. However, with a niche solution such as Jmix, the same work can be done by a single developer. This allows for a more streamlined process, while still producing a modern functional, and visually appealing interface. Additionally, code generators can significantly accelerate the creation of repetitive CRUD screens. 

This approach has some drawbacks, and one of them (the session replication issue) can be critical. However, for building business-oriented applications with heavy data load, using Jmix seems to be a more reasonable and efficient solution compared to the traditional Spring Boot + React stack. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar Recap: Choosing the Right Delivery Strategy with Jmix]]></title>
            <link>https://www.jmix.io/blog/webinar-recap-choosing-the-right-delivery-strategy-with-jmix</link>
            <guid>https://www.jmix.io/blog/webinar-recap-choosing-the-right-delivery-strategy-with-jmix</guid>
            <pubDate>Thu, 03 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/1080h1920_without_date_62a025ba49.png">In this webinar we dive into different delivery models supported by Jmix.]]></description>
            <content:encoded><![CDATA[The webinar explored how product teams can efficiently build and deliver scalable, maintainable digital products using the Jmix platform. It focused on solving common problems in B2B software delivery like managing endless client customizations, code forks, and growing maintenance costs. 

Viktor Fadeev, Jmix Product Manager, introduced Jmix as a rapid app development platform for Java teams. It combines a powerful framework, visual Studio plugin for IntelliJ, and a marketplace of ready-made add-ons. With Jmix, teams can build digital products faster, with a clear structure and using full-stack tools.  

The session covered three key delivery models supported by Jmix: 

**Extension Model**

Package core functionality into reusable add-ons, and allow client-specific extensions without changing the base code. Great for niche products where each client has different needs. 

**SaaS Model** 

Use Jmix’s built-in multi-tenancy features to deliver one shared application for many clients. Ideal for scaling across SMBs. But as the product grows, you’ll need to manage challenges like performance, database scaling, and customization limits. 

**Self-Hosted Model**

Perfect for industries with strict regulations. Deliver isolated deployments with full control and source code access. Jmix’s composite projects help split large systems into manageable modules, reducing duplication and improving development speed. 


**Key Takeaways** 

- “Copy-paste and pray” doesn’t scale - modular delivery is essential for long-term success. 
- Jmix helps avoid code forks with clear boundaries between core logic and client-specific features. 
- Multi-tenancy is available out-of-the-box and works well for SaaS models with minimal customization. 
- Composite projects simplify self-hosted delivery, especially for complex enterprise clients. 
- Early consulting and training reduce risk - get architecture right from the start. 

 
**Summary** 

Jmix offers the tools and structure needed to quickly deliver robust, scalable digital products. Whether you're targeting niche clients, growing SaaS, or serving regulated industries, picking the right delivery model makes all the difference. 

<iframe class="b-youtube-player" width="640" height="360" src="https://www.youtube.com/embed/y8VL3gG-as0?si=Hl4vCq_pdNwIyK4B" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Logistic and transportation automation system – Jmix]]></title>
            <link>https://www.jmix.io/blog/logistics-automation</link>
            <guid>https://www.jmix.io/blog/logistics-automation</guid>
            <pubDate>Tue, 01 Jul 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_Blog_Industries_Logistics_f73fc0b632.png">The logistics industry has been impacted by digitalization and its effects on closely linked industries such as retail and the rise of e-commerce. The pace of change in logistics has been disrupted by supply chain issues across the globe in recent years. New economical reality have highlighted the urgency needed to ensure a cost-efficient recovery for the industry.]]></description>
        </item>
        <item>
            <title><![CDATA[Jmix 2.6 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-2-6-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-2-6-is-released</guid>
            <pubDate>Mon, 30 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/jmix_2_6_b6baf1a46c.png">Overview of the new features and important changes of the Jmix 2.6 feature release.]]></description>
            <content:encoded><![CDATA[We are pleased to announce the release of Jmix 2.6, which includes new features, enhancements, and performance improvements. This release brings significant updates to Jmix Studio, introduces new UI components, and boosts productivity with smarter tools and integrations. 

Below is a quick overview of Jmix 2.6's key features.

## Studio Improvements

### Jmix AI Assistant

The Jmix AI Assistant is now integrated into Jmix Studio tool window. This assistant shares chat history with the web-based version, enabling seamless transitions between Studio and web browser, so you can pick up right where you left off.

![ai-assistant]({{strapiUrl}}/uploads/Pasted_image_20250626132808_b1922b3c2a.png)

### New Code Snippets

Jmix 2.6 adds over 20 new UI-related code snippets, covering notifications and dialogs, opening views and fragments, asynchronous execution, and API examples. These snippets make it faster and easier to implement common UI patterns in your projects.

<img src="{{strapiUrl}}/uploads/Pasted_image_20250626133325_76d1c2cdc3.png" width="647">

### Moving Views

Relocating views is now simpler with the _Move View_ context menu action in the Jmix tool window. This feature moves both the Java controller and XML descriptor together, automatically updating message keys in the message bundle. Additionally, when moving a Java controller or XML descriptor in the Project tool window, Studio prompts you to relocate the corresponding file and update message keys.

<img src="{{strapiUrl}}/uploads/Pasted_image_20250626133443_f0cba6eb94.png" width="419">

### Scaffolding Renderers

Generating renderers for UI components, such as `dataGrid` columns, is now more intuitive. Studio offers a wizard to scaffold `ComponentRenderer`, `TextRenderer`, or an empty handler method, simplifying the creation of custom UI renderers.

### Replacing Strings with Localized Messages

A new _Replace with localized message_ intention action, available in both Java and XML code, lets you quickly replace string literals with localized messages from the message bundle.

For example, imagine that you have the following code in a view descriptor:  
```java
@Subscribe  
public void onInit(final InitEvent event) {  
    someLabel.setText("Hello World");  
}  
```  
  
Put cursor on the "Hello World" string and press `Alt-Enter`. Select *Jmix: Replace with localized message* action, and Studio will show a dialog for creating a localized message. After entering the message key and clicking *OK* the code will be changed to the following:  

```java
@ViewComponent  
private MessageBundle messageBundle;  
  
@Subscribe  
public void onInit(final InitEvent event) {  
    someLabel.setText(messageBundle.getMessage("label.text"));  
}  
```

### Lombok Support

Studio now supports `@Getter` and `@Setter` annotations on entities and `@RequiredArgConstructor` on Spring beans, avoiding redundant code generation. It also warns developers about using `@EqualsAndHashCode` or `@Data` annotations on entities, which can cause issues due to incorrect equals/hashCode implementation.

### Performance on Large Projects

Performance has been significantly enhanced for large projects. The Jmix tool window’s project tree and resource role designer now operate smoothly, even in projects with over 1,000 entities.

## New UI Components and Features

### Switch Component

Introducing the new **Switch** component, which allows users to toggle between two states (e.g., on/off or true/false). Designed to resemble a physical toggle switch with a sliding handle, it adds a modern touch to your UI.

<img src="{{strapiUrl}}/uploads/Pasted_image_20250626163030_a25a42df2b.png" width="264">

### Tabbed Application Mode Improvements

The **Tabbed Application Mode** add-on is now production-ready with several enhancements:

- The `mainTabSheet` component is explicitly defined in the main view layout, supporting actions via the tab context menu or keyboard shortcuts and ability to drag-and-drop tabs.
- The `@TabbedModeViewProperties` annotation for defining view parameters in tabs.
- Preserved UI state and firing `UIRefreshEvent` on web page refresh.

![Pasted image 20250626164513.png]({{strapiUrl}}/uploads/Pasted_image_20250626164513_50c3430c60.png)

### Autocompletion in CodeEditor

The `codeEditor` component now supports autocompletion for specific language modes or custom suggestion handlers. 

<img src="{{strapiUrl}}/uploads/Pasted_image_20250626171833_5e3442966e.png" width="570">

### HorizontalLayout Slot Placement

The `hbox` component now supports adding components to `start`, `center`, or `end` alignment slots, offering simplified component positioning within the `HorizontalLayout`. For example:

```xml
<hbox id="horizontalBox" width="100%" css="border: 1px solid black;" padding="true">  
    <startSlot>  
        <textField label="Start component" width="9em"/>  
    </startSlot>  
    <middleSlot>  
        <textField label="Middle component" width="9em"/>  
    </middleSlot>  
    <endSlot>  
        <textField label="End component" width="9em"/>  
    </endSlot>  
</hbox>
```

![Pasted image 20250626174227.png]({{strapiUrl}}/uploads/Pasted_image_20250626174227_afe4fec970.png)

### Export/Import of Message Templates

The **Message Templates** add-on now supports _Export_ and _Import_ actions, enabling easy transfer of templates between applications.

## REST DataStore Enhancements

The REST DataStore add-on simplifies invoking remote services exposed via REST API. Now you only need to create an interface mirroring service methods and annotate it with `@RemoteService`. 

The add-on now includes the `restds_RestOidcAuthenticator` bean that allows you to use an external authentication provider (for example Keycloak) when integrating applications.

## Masquerade UI Testing Library

Jmix 2.6 introduces Masquerade, an end-to-end UI testing library tailored for Jmix applications. Built on Selenium WebDriver and Selenide, Masquerade simplifies testing by providing convenient wrappers and streamlining access to web element functions.

## Updated Dependencies

The Jmix 2.6 release includes updates to major dependencies:

- Spring Boot has been updated to version 3.5.
- Vaadin has been updated to version 24.7.

These updates ensure that Jmix continues to be built on a modern, secure, and performant foundation.

## Future Plans

The next feature release is expected in October 2025. We will focus on the following functionality:

- Grouping DataGrid component
- UserMenu component
- Data model visualization
- SAML add-on
- Ability to define reports in Java code
- Reverse engineering: generate attributes from database columns for already mapped entities

## Conclusion

Jmix 2.6 introduces powerful new features and enhancements designed to boost developer productivity and enrich application capabilities.

If you have a question, want to share feedback, or simply connect with others, join us on the <a href="https://forum.jmix.io/" target="_blank">forum</a> or <a href="https://join.slack.com/t/jmixplatform/shared_invite/zt-2juulpoaf-7yp7F~m_fhFDmZ6GXHr83A" target="_blank">Slack</a>.

A big thank you to everyone in the community for your valuable contributions. We hope Jmix 2.6 brings even more success to your projects!
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Everything a BPM Developer Should Know About Process Variables]]></title>
            <link>https://www.jmix.io/blog/everything-bpm-developer-should-know-about-process-variables</link>
            <guid>https://www.jmix.io/blog/everything-bpm-developer-should-know-about-process-variables</guid>
            <pubDate>Thu, 26 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Process_variables_Process_Variables_55f94c1b60.png">In this article, we talk about process variables: what they’re for, how they differ from programming variables, and how scope works.]]></description>
            <content:encoded><![CDATA[This article continues the <i>BPMN: Beyond the Basics</i> series – a look at the practical, less-discussed aspects of working with BPMN for developers. Today, we’ll talk about process variables: what they’re for, how they differ from programming variables, and how scope works. At first glance, it might seem like there’s nothing special about them, but if you dig below the surface, there’s more nuance than expected. In fact, we couldn’t fit it all into one piece article, so we’re splitting this topic into two parts. 

## Data in a Process 

Process modeling traditionally begins with actions: approve a document, submit a request, sign a contract, plant a tree, deliver a pizza. Data is often left in the background, as if the performer intuitively knows where to get the right document or which pizza to deliver. 

That works in human-centered, descriptive processes. People are expected to understand context, navigate loosely defined inputs, and follow general instructions. That’s why process models often resemble enhanced job descriptions more than software logic. 

But when we move into automation, especially full automation, the game changes. A process without people must be **explicit about how it handles data**. It becomes not just a chain of steps, but a **data processing mechanism**. And if you want that mechanism to run fast and reliably, you need to understand how data is passed in, stored, transformed, and retrieved. 

In short, a business process without data is like a horse without a cart — it might go somewhere, but it’s not carrying any value. 

## Data-Centric Processes and BPM Engines 

Even though classic processes like document flow and multi-step approvals are still important for many companies, the shift toward full automation is well underway. Gartner <a href="https://www.venasolutions.com/blog/automation-statistics" target="_blank">predicted</a> that by 2025, 70% of organizations will have adopted structured automation—up from just 20% in 2021. And the whole workflow automation market? According to Stratis Research <a href="https://straitsresearch.com/report/workflow-automation-market" target="_blank">report</a>, the workflow automation market is expected to top $45 billion by 2032, which shows just how much everyone wants to automate everything from start to finish. 

Why the rush? It’s mostly about cutting down on mistakes, saving money, and speeding things up. Some studies (<a href="https://gitnux.org/workflow-automation-statistics/" target="_blank">Gitnux</a>) say automation can reduce errors by as much as 70% and lets people focus on more interesting, higher-value work. So, fully automated processes—where data processing and orchestration are front and center—are quickly becoming the new normal in digital transformation, not just a nice-to-have. 

 Let’s see how ready our BPM engines are for this. Spoiler: not very. 

<i>“BPMN does not provide a comprehensive data model. Data Objects and Data Stores are used to show that data is required or produced, but their structure is not defined.” 

— “BPMN 2.0 Handbook: Methods, Concepts, and Techniques for Business Process Modeling and Execution” (2011) 

“BPMN is not intended to model data structures or detailed data flows.” 

— Bruce Silver, “BPMN Method and Style” (3rd Edition, 2016) </i> 

BPMN notation was originally created as a language for describing processes and does not include data models. Everything related to data in it is limited to so-called  ```Data Objects```, which only hint that some kind of data or documents are used in the process (judging by their icon). There is also the ```Data Store```, which pretends to be a database or some information system, again based on its appearance. 

![Picture1.jpeg]({{strapiUrl}}/uploads/Picture1_887fa84ab6.jpeg)

In essence, these are just graphical symbols. Their role is limited to informing the diagram reader that some data exists in the system and there is interaction with storage. There is no engine-level implementation behind them. 

As a result, we have a situation where there are clear rules for modeling the process itself according to the BPMN 2.0 standard, which are implemented in a very similar way (if not identically) across engines. But there is no unified mechanism for working with data — each developer decides how to handle it on their own. 

On the one hand, this is good — freedom! You can choose the optimal solution for your tasks. On the other hand, the lack of clear rules often leads to fewer than ideal data handling solutions in projects. 

## Why Do We Need Process Variables? 

So, at the BPMN model level, we don’t have data as such — the diagram describes the structure and logic of the process but does not operate directly with variables. However, when the process is executed, data becomes necessary: somewhere you need to save user input, somewhere to make a decision, and somewhere to send a request to an external system. All this data exists in the form of process variables, which are “attached” to each process instance and accompany it throughout its execution. 

Broadly speaking, process variables fulfill four roles: 

- Data transfer between steps 
- Process flow control 
- Interaction with the user 
- Integration with external systems 

![Picture2.png]({{strapiUrl}}/uploads/Picture2_7cebe27155.png)

Process variables help carry information through the entire process, from start to finish. For example, a user fills out a loan application form, and the data they enter (amount, term, loan purpose) is saved into variables. Then these values are used in service tasks, passed to gateways, and determine which branches should be activated. In one branch, a variable may be updated or supplemented and then passed further, for example, to a verification or notification task. 
  
They also allow us to control the behavior of the process during execution. Suppose we have a variable called ```priority```, calculated based on the application parameters. If, at the process start, it equals "high," the task is automatically routed to a specific specialist; otherwise, it goes into a general queue. 

When the process interacts with a user, variables become the link between the form and the process logic. They are used both to display data and to receive user input. If a variable was already set on a previous step — for example, ```userEmail``` — its value can be shown in the form. The user, in turn, fills in other fields, and their values are saved back into variables to be used later in the process. Thus, the form works as a “window” into the current execution context: everything the process knows at this point is available to the user, and everything the user enters remains in the process. 

 Finally, process variables are a communication channel with the outside world. When a service task calls a REST API, it can use variables as input parameters and save the response to a variable. This response can then be analyzed, logged, passed to another service, or displayed to the user. 

## The Lifecycle of a Variable 

Now let’s talk about how process variables are born, live, and end their lifecycle. To do that, we first need to look at how they are structured. 

In BPM systems such as Camunda, Flowable, or Jmix BPM, process variables are objects that store not only their value but also metadata about themselves. In other words, they’re not simple variables like in Java or another programming language — they’re containers that hold data. 

Why make it so complicated? Because a process can run for a long time — hours, days, or even months. That’s why the values of variables need to be stored in a database, so they can be retrieved later when needed. And if we write something to the database, metadata appears as well—it’s only logical. 

### Creation and Persistence of Variables 

<u>Note: The examples in this section are based on the Flowable engine. </u>

So, data has entered the process — for example, as a payload in the start message, in the form of a ```Map<String, Object>```. What does the engine do next? First, it creates a process instance — ```ProcessInstance``` — and initializes its execution context. Then the engine automatically saves all passed variables into this context using the ```setVariable``` method. But it’s important to understand: the engine doesn’t just “store” values somewhere in memory. It wraps each variable according to its type into an internal entity called ```VariableInstanceEntity```, making the variables immediately accessible throughout the process — in scripts, transition conditions, tasks, and so on. 

Additionally, a developer can create a variable in code whenever needed, also using the ```setVariable``` method — including from Groovy scripts: 

```runtimeService.setVariable(executionId, "docStatus", "APPROVED"); ```

As long as the process hasn't reached a transaction boundary, no database writing occurs. The variable remains in an in-memory structure — a ```List<VariableInstanceEntity>``` within the ```ExecutionEntity```. This is convenient: the next task or script can be used without hitting the database. 

However, once the process hits a wait state — such as a message or signal event, timer, user task, event-based gateway, or asynchronous task — the transaction is committed, and all entities created or modified during the transaction are flushed to the database. This includes process variables, which are written to the ```ACT_RU_VARIABLE``` table. 

![Picture3.png]({{strapiUrl}}/uploads/Picture3_861083b5f5.png)

If the variable type is a primitive, it is stored as-is in the corresponding field of the table. Non-primitive variables, on the other hand, are serialized before being saved — and stored either as strings or byte arrays. 

### Table Fields (Translated from Russian) 

| Field         | Type             | Purpose                                                                                                                                      |
|---------------|------------------|----------------------------------------------------------------------------------------------------------------------------------------------|
| `id_`         | `varchar(64)`    | Unique variable ID. Primary key of the table.                                                                                                |
| `rev_`        | `integer`        | Record version (used for optimistic locking when updating the variable).                                                                     |
| `type_`       | `varchar(255)`   | Variable type (e.g., string, long, boolean, serializable, json, object, bytearray, etc.). Determines which value fields are used.             |
| `name_`       | `varchar(255)`   | Variable name.                                                                                                                               |
| `execution_id_`| `varchar(64)`   | ID of the specific execution the variable is linked to.                                                                                      |
| `proc_inst_id_`| `varchar(64)`   | ID of the process the variable belongs to. Used for retrieving variables by process.                                                         |
| `task_id_`    | `varchar(64)`    | Task ID if the variable is scoped at the task level.                                                                                         |
| `scope_id_`   | `varchar(255)`   | Used only in CMMN.                                                                                                                           |
| `sub_scope_id_`| `varchar(255)`  | Used only in CMMN.                                                                                                                           |
| `scope_type_` | `varchar(255)`   | Scope type (bpmn, cmmn, dmn). Not actually used in practice.                                                                                 |
| `bytearray_id_`| `varchar(64)`   | ID of the entry in the `act_ge_bytearray` table where the variable value is stored (if it's a byte array or a serialized object).            |
| `double_`     | `double precision`| Variable value if the type is double.                                                                                                     |
| `long_`       | `bigint`         | Variable value if the type is long, integer, short, or boolean (as 0/1).                                                                     |
| `text_`       | `varchar(4000)`  | Variable value if the type is string, json, date, or uuid. May also hold serialized values as text.                                          |
| `text2_`      | `varchar(4000)`  | Additional text field, e.g., for serialization format or extra parameters. May be used in JSON/XML serialization.                            |
| `meta_info_`  | `varchar(4000)`  | Metadata about the variable, such as object class (if it's a serialized object), or other engine-relevant info. Not used in Jmix BPM.        |
 

Once a variable is written to the ```ACT_RU_VARIABLE``` table, it becomes part of the process's persistent state. This means that even if the server is restarted, the process can be restored and resumed — along with all its variables. At this point, the cache is also cleared, and the ```VariableInstanceEntity``` objects are removed from memory. 

In some cases, however, you may want a variable **not** to be stored in the database, for example, intermediate calculation results that aren’t needed in later steps of the process, or sensitive data like passwords, authorization tokens, and similar. In such cases, variables can be declared **transient** and will be kept in memory only. But this is up to the developer — by default, all variables are persistent. 

### Reading and Updating Variables 

Now let’s take a look at how variable reading works. 

![Picture4.png]({{strapiUrl}}/uploads/Picture4_f9233266e6.png)

After one transaction is successfully completed, the next one begins, and a new variable cache is created. Initially, this cache is empty — variables are not loaded by default. Only when a variable is actually needed does the engine execute a command like: 

```String status = (String) runtimeService.getVariable(executionId, "docStatus"); ```

First, the engine locates the corresponding ```ExecutionEntity``` using the given ```executionId```. This is the **execution context** that holds variables associated with a specific active step of the process. If the variable is not yet in memory, the engine issues an SQL query to the ```ACT_RU_VARIABLE``` table. The retrieved object is then deserialized (if necessary), added to the ```ExecutionEntity``` cache, and returned to the calling code. 

If you need not just the value but the full variable information including metadata, you can request a ```VariableInstance``` object: 

```VariableInstance statusVar = runtimeService.getVariableInstance(executionId, "docStatus"); ```

Keep in mind, though, that this is a **read-only** object. If you want to update the variable, you must call ```setVariable``` again. The new value will be written to the database during the next commit. Technically speaking, this is not an update, but rather the creation of a new variable with the same name. 

And here’s a subtle point: the engine does not enforce type consistency. So, if the variable originally held a string, and you later assign a number to it, the engine will accept it without complaint. However, this may lead to issues later — for example, when accessing historical data or using the variable in other steps of the process. 

### Deleting Variables 

When a process (or execution) ends, its variables are deleted. That is, all entries in the ```ACT_RU_VARIABLE``` table associated with the specific ```executionId``` are removed. 

A developer can also proactively delete a variable before the process finishes: 

```runtimeService.removeVariable(executionId, "largePayload"); ```

Normally, this isn’t necessary just for “clean-up” purposes — the engine handles that on its own. 

However, there are situations where proactively removing variables can be useful. For example, when a variable contains a large amount of data — say, a JSON object several megabytes in size or a high-resolution image. Keep in mind, this data is stored in the database, not in the Java process memory — so we’re not talking about garbage collection here, but about reducing database load. 

If a variable contains personal or sensitive data (like temporary passwords or one-time codes) and is no longer needed after use, it should be deleted. 

Some variables are used only within a single step (for example, intermediate results). These can be removed after that step finishes to avoid confusion or accidental reuse. 

To avoid dealing with deletion altogether, it's often better to declare such variables as **transient** right from the start. 

<i>Transient means that the variable is temporary and not saved permanently (for example, not stored in a database or persisted between sessions). It exists only during the runtime or the current process and disappears afterward. </i>

### Writing to History 

A key principle is that historical records for variables are **not** created when the process finishes, but rather **at the moment the variable is set** (```setVariable```), if history tracking is enabled. This is controlled by the ```historyLevel``` parameter. 
<br/>  

| historyLevel | Description                  | What Is Stored                                                                 |
|--------------|------------------------------|--------------------------------------------------------------------------------|
| `none`       | History is completely disabled | Nothing                                                                        |
| `activity`   | Minimal history: tracks process activity | Process start/end, tasks, events                                               |
| `audit`      | More detailed history         | Everything from `activity` + variables (latest value only)                     |
| `full`       | Complete history, including changes | Everything from `audit` + all variable changes (`ACT_HI_DETAIL`)               |

<br/>  
By default, the engine uses the ```audit``` level — a compromise between useful historical data and performance. 

 So, in most cases, history is enabled. When a variable is created, its value is also written to the ACT_HI_VARINST table. More precisely, a ```HistoricVariableInstanceEntity``` is created and inserted into that table when the transaction is committed. 

 If ```historyLevel = full```, **every** change to the variable is also recorded in the ```ACT_HI_DETAIL``` table. 

 **Important Note**

BPM engines do not provide a unified mechanism for working with variables. Variables can appear anywhere — as a field in user form, as a payload in a message or signal, or declared in script code, Java delegates, or Spring beans. 

All of this is entirely the developer's responsibility. Your IDE won’t be able to help. That’s why extreme attentiveness is required. One day, you may want to fix a typo in a variable name — but there will be no way to automatically track down all the places where it’s used. 

### Scope 

Like regular variables, process variables have scope. But this concept works quite differently in BPM than in programming languages. Just accept it as a fact and don’t rely on intuition — it can easily mislead you. 

In programming, a variable scope is defined lexically, — depending on the class, method, or block where it is declared. It doesn’t matter whether the language uses static typing, like Java, or dynamic typing, like Python. 

Process variables are something entirely different, as Monty Python might say. Essentially, they are not just variables but runtime objects. Therefore, the lexical approach doesn’t apply here. And although you can declare variables in a BPMN model, it’s not a true declaration like in programming. It’s more like a description of intent — the engine doesn’t require these variables to exist until they are actually set. 

For example, in Jmix BPM, you can define process variables in the start event. Such declarations are useful for documentation purposes, so anyone reading the model understands which variables are used. And if the process is started programmatically, explicitly listing the variables helps the developer know what parameters are needed to start it. 

![Picture5.jpeg]({{strapiUrl}}/uploads/Picture5_6266afbb22.jpeg)

But they will not appear in the process by themselves. They must either be passed as parameters or created at some subsequent step using the setVariable method. Otherwise, if you try to access them, the system will throw an error stating that such an object does not exist. 

As we discussed in the first part of this article, process variables are created as a result of calling the ```setVariable``` method. Their scope is determined by their "birthplace," almost like citizenship — that is, the execution context in which they were created. 

When a process instance starts, the engine creates a root execution context (the process instance). Then, as the process progresses, these contexts form a hierarchical structure. For example, when the flow encounters an embedded subprocess, a parallel gateway, an asynchronous task, and so on, a new execution context is created. Subsequently, child contexts arise relative to previous ones. Thus, execution contexts form a tree. 

 Accordingly, the scope of variables is defined by the position of their execution context within this tree. Variables created in a higher-level context are visible in all the lower levels beneath them. 

 Let’s take a process as an example and mark all its execution contexts: 

![Picture6.png]({{strapiUrl}}/uploads/Picture6_3f23116a4d.png)

Then, represented as a tree, it will look like this: 

![Picture7.jpeg]({{strapiUrl}}/uploads/Picture7_9e0bc84963.jpeg)

If we define the variable ```orderId``` at the top level of the process, it will be accessible everywhere. But a variable like ```discount```, if it is set in the first parallel branch, will only be visible within its own execution context and cannot be accessed later outside of it. So, it’s important to plan variable declarations with their scope in mind. 

A nested subprocess not only helps to structure execution logic but also creates a new scope — and this can actually be its more important feature. 

A separate story applies to external subprocesses (<i>call activities</i>). Each such call is wrapped in its own execution context. That’s why in the second parallel branch we see another nested <i>execution</i>. But the external subprocess itself runs as a completely separate instance, and by default does not see variables of the parent process. You must explicitly map variables to pass them into the child process — and similarly map them back if needed. 

If you have event subprocesses, each one lives in its own <i>execution</i> and waits to be activated. There are no special tricks here — it sees all process-level variables plus its own. 

When a <i>multi-instance task</i> occurs on the path, first a common execution context is created (in our example — <i>execution 2</i>) which tracks all instances. Then each instance gets its own separate execution context. A common mistake here is when someone tries to write a variable at the top level from a specific instance — for example, in parallel document approvals. As a result, all approvers overwrite the same variable, and you only see the decision of the last approver. The key here is not to get confused by all these variables, which are often named the same. 

This situation is resolved by local variables, which we will discuss below. 

## Local Variables 

If you set a variable in the usual way, it will be visible to all child executions. But if you use the method ```setVariableLocal```, it will be “locked” within the current execution and won’t be visible outside of it, including in lower-level contexts. 

Okay. But why would you need to guarantee that a variable is not passed down the hierarchy? 

Actually, this isn’t the main purpose. Local variables help keep things organized in your process: when you declare a variable as local, you make sure it won’t accidentally overwrite a variable with the same name in a broader (global or parent) scope. 

Returning to our approval example: when in each instance of the multi-instance subprocess we explicitly specify that the comment field and the document decision are local variables, the chance of confusion is reduced. 

In general, local variables are a mechanism for isolation and error prevention rather than a functional necessity. They do not solve problems that couldn’t be solved otherwise, but they do it more safely and cleanly. 

## Variable Shadowing 

What if variables have the same names? 
 
This can happen — you create a variable in a child execution context with the same name as one already presented in the parent. In this case, variable shadowing occurs — the parent variable becomes inaccessible in the current context, even though it still exists in the execution tree. 

**How it works**

Each execution context contains its own set of variables. When accessing a variable via the method ```getVariable(String name)```, the engine first looks for it in the current execution. If the variable is found — it is used, even if a variable with the same name exists at a higher level. Thus, the higher-level variable is “shadowed.” 

```// Somewhere at the start of the process 
execution.setVariable("status", "CREATED"); 

// Inside a task or subprocess: 
execution.setVariableLocal("status", "PROCESSING"); 

// What will a script or service see in this execution? 
String currentStatus = (String) execution.getVariable("status"); // "PROCESSING" 

```

Although the parent variable still exists, the child variable overrides it within the current execution. Once you exit the scope of the child context (for example, when the subprocess ends), the higher-level variable becomes visible again. 

Variable shadowing can be useful when used correctly, but it also represents a potential source of errors. In some scenarios, it provides an advantage — for example, allowing you to temporarily override a variable without changing its original value. This is especially convenient in multi-instance constructs where each instance works with its own copy of data.  

However, shadowing can lead to unexpected results if you are not sure which context, you are in. Debugging becomes more difficult: in the history, you may see a variable with the same name, but it’s not always clear at what level it was created or why its value differs. 

 To avoid such issues, it’s recommended to follow several guidelines. It’s better to use different variable names if they have different meanings or belong to different execution levels.  

 Also, consciously manage the context in which variables are created and avoid using ```setVariableLocal``` unless there is a clear need. When analyzing process state, it is helpful to check variables at the current and parent levels separately using ```getVariableLocal()``` and ```getParent().getVariable()``` to get the full picture. 

## Types of Process Variables 

As for variable types, their variety depends on the engine developer — as mentioned earlier, the specification does not define this, so each implementation does its own thing. Of course, there is a common set that includes primitive types — strings, numbers, boolean values, as well as dates. But even here there are differences — compare the two illustrations and see for yourself. 

In Camunda, we have one set of data types, while in Jmix BPM (with the Flowable engine) it is somewhat different. 

![Picture8.jpeg]({{strapiUrl}}/uploads/Picture8_d9511615d6.jpeg)

Regarding the basic types, this difference is insignificant and may only become apparent when migrating from one engine to another. But there are some interesting distinctions worth mentioning. 

You’ve probably noticed that Camunda supports JSON and XML types. However, this is not a built-in feature of the engine itself — to work with them, you need a special library called **Camunda Spin**, designed for handling structured data within business processes. It provides a convenient API for parsing, navigating, and modifying data, as well as automatically serializing and deserializing data when passing it between tasks. This can be especially useful when processing responses from REST services, storing complex structures as variables, and generating XML/JSON documents. 

![Picture9.jpeg]({{strapiUrl}}/uploads/Picture9_05ff60b6ad.jpeg)

In turn, Jmix BPM allows you to use elements of the Jmix platform’s data model as process variables — entities, lists of entities, and enumerated types (Enums). This is especially helpful when you need to manipulate complex business objects within a process that contains dozens of attributes. For example, applications, contracts, support tickets, and so on. 

<h2 style="color:3368ff">Entity Data Task — Accessing the Data Model from the Process </h2>

Jmix BPM includes a special type of task called the Entity Data task. With it, you can create new entity instances, modify them, and load individual entities or collections of entities obtained via JPQL queries directly into process variables right from the process. This is not an extension of the BPMN notation per se. Technically, these are just regular service tasks with a specific set of parameters. 

Thus, you can model a process in a low-code style — using User tasks for user actions and Entity Data tasks for data manipulation. If no complex integrations or logic are required, this approach is often sufficient. 

Let’s consider a hypothetical example. Suppose some data arrives. The system checks whether it relates to an existing customer order or not. Depending on the result, it executes one task or another; either creating a new Order entity or loading/finding an existing one. Then, an employee performs some work, and an Entity Data task updates the modified attributes of the entity. 

![Picture10.jpeg]({{strapiUrl}}/uploads/Picture10_2478e58f17.jpeg)

Of course, a real process would be more complex — this diagram merely illustrates the concept of how you can use an Entity Data task to work with data. 

## Limitations 

This section outlines the limitations of process variables in different BPM products. 

### Camunda 

**String Length Limitation** 

In Camunda, values of type String are stored in the database in a column of type (n)varchar with a length limit of 4000 characters (2000 for Oracle). Depending on the database and configured character encoding, this limit may correspond to a different number of actual characters. Camunda does not validate the string length — values are passed to the database “as is.” If the allowed limit is exceeded, a database-level error will occur. Therefore, it's the developer’s responsibility to control the length of string variables. 

**Context Size Limitation** 

Although process variables are stored in a separate database table, in practice, there is a limit to the total amount of data associated with a process instance. This limit is not so much about the physical storage but rather the internal mechanisms of serialization, memory loading, transactional handling, and other engine internals. A typical safe threshold is around **3–4 MB** per process context. This includes serialized variables, internal references, events, and other metadata. The exact value depends on the DBMS, serialization format, and engine configuration. 

Storing too many variables or large documents in the process context can lead to unexpected ```ProcessEngineExceptions``` due to exceeding the allowable size of a serialized object. Therefore, when working with large variables, it is recommended to stay well below this limit and conduct performance testing if needed. 

In **Camunda 8**, there is a strict limit on the size of data (<i>payload</i>) that can be passed into a process instance. The total maximum size of all process variables is **4 MB**, including engine internals. However, considering overhead, the safe threshold is around **3 MB**. 

### Flowable / Jmix BPM 

**String Length Limitation** 

Flowable handles strings a bit differently: if the length of a ```String```-type variable exceeds 4000 characters, it is automatically assigned an internal type of ```longString```. Its value is then stored as a byte array in the ```ACT_GE_BYTEARRAY``` table, while the ```ACT_RE_VARIABLE``` table contains a reference to it. As a result, Flowable does not impose any explicit limit on string length. 

In theory, the length of a string variable is only limited by the Java maximum — 
```Integer.MAX_VALUE = 2,147,483,647``` 
(roughly 2.1 billion characters). 
However, in practice, the effective limit is determined by available heap memory. 

**Entity List Size Limitation**

For variables of type ```Entity List```, there is a constraint related to the way they are stored. When saved to the database, such variables are serialized into a string format like: 

```<entityName>."UUID"``` — for example: 
```
jal_User."60885987-1b61-4247-94c7-dff348347f93" 
```

This string is saved in a text field with a maximum length of 4000 characters. As a result, the list can typically contain around **80 elements** before exceeding the limit. However, this restriction only applies at the point of database persistence — in memory, the list can be of any size. 
 
**Context Size Limitation**

Flowable (and thus Jmix BPM) does not enforce a hard limit on the size of the process context. Still, it's recommended to keep the context as small as possible, since a large number of process variables can negatively impact performance. Also, you might eventually run into limits imposed by the underlying database system. 

## Process Variables in Groovy Scripts 

Scripts in BPMN are often underrated, yet they are a powerful tool—especially lightweight, in-process logic. They're commonly used to initialize variables, perform simple calculations, log messages, and so on. BPM engines typically support **Groovy** or **JavaScript** as scripting languages, with **Groovy** being more prevalent due to its concise syntax, native Java compatibility, and ease of use when working with process objects. The most important of these is the execution object, which represents the process context and allows you to work with process variables. 

Your main workhorses are the familiar ```setVariable``` and ```getVariable``` methods, used to write and read process variables. However, there's a feature that—while seemingly convenient—can lead to hard-to-diagnose bugs: 
 
**process variables in Groovy scripts are accessible directly by name.**
 
That means you can reference them in expressions without explicitly reading them first: 

```amount = price * quantity ```

But here’s the catch: 
  
**The assignment operator does not affect process variables.**
 
So, after that expression, the value of the amount process variable will **not** change. To actually update it, you must explicitly call ```setVariable```: 

```execution.setVariable("amount", price * quantity) ``` 

This is because a process variable is part of the execution context, not just a regular Groovy variable—it must be handled explicitly.  

To complicate things further, Groovy allows you to define **local script variables** on the fly. Since Groovy is a dynamic language, it will silently create a new script variable if one isn't already defined. So, if you haven’t explicitly created the process variable amount, the following line will still work: 

```
amount = price * quantity 
execution.setVariable("amount", amount) 
```

And there's more to it! Even though Groovy doesn’t require it, **declaring variables explicitly** using def is considered best practice. It helps avoid subtle bugs: 

```
def amount = price * quantity 
... 
execution.setVariable("amount", amount) 
``` 

Now everything is clean and correct. Right? — Well, almost. 

When your script task is marked as **asynchronous**, this convenient implicit access to process variables by name might break. 
 
Consider the following line in an asynchronous script: 

```
execution.setVariable("counter", counter + 1L) 
```

You might get a confusing error like: 

```
groovy.lang.MissingPropertyException: No such property: counter for class: Script2 
```

This means the variable counter wasn't available in the script context at execution time. 
Why? Because engines like Flowable inject process variables into the script environment **automatically**, but for **asynchronous executions**, this may happen **too late**—after the script has already started running. 

To avoid this issue, always **explicitly read** the variable at the start of the script: 
```
def counter = execution.getVariable("counter") 
execution.setVariable("counter", counter + 1L) 
```
And just like that — no more exceptions! 

## Best Practices 

Working with process variables is a key part of building reliable business processes. Variables allow the process to “remember” data, pass it between tasks, and make decisions. However, without discipline, they can easily become a source of bugs—from subtle logic errors to critical failures. This section outlines proven practices to help you avoid common pitfalls and build a clean, predictable data model in your process. 


1. **Use clear and unique variable names**
Choose meaningful and descriptive names. Avoid duplicates. 
Good: orderApprovalStatus 
Bad: status 
<br/>
 
2. **The fewer variables, the better**
Keep in mind that the process context isn’t unlimited. Avoid creating unnecessary variables. Even without hard size limits, bloated contexts hurt performance. 
Avoid storing large documents or massive JSON structures directly—store them as files and keep only a reference in the process. 
<br/>
3. **Use transient variables for temporary data**
If data is only needed within a single action or expression, define it as ```transient```. It won’t be saved to the database or show up in history. 
<br/>
4. **Be cautious with entity variables**
Many BPM platforms support storing complex objects (e.g. entities) in process variables. This is convenient for business logic involving entity attributes. 
However, if you load an entity into a variable at the start of the process, and later display it in a form days later, can you be sure it hasn’t changed? — Definitely not. 
Instead, store the entity’s **ID** as a variable and re-fetch it when needed. 
<br/>
5. **Serialization may surprise you** 
When saving complex objects, the engine serializes them before writing to the DB. Not all Java objects can be stored—your object must either implement ```Serializable```, or you must provide and register a custom serializer. 
Also, serialization may behave differently in regular vs. asynchronous tasks, since async tasks run in the ```JobExecutor``` which has a different context. 
<br/>
6. **Link entities to processes**
Often, a process is started in relation to an entity—an order, document, customer request, etc. You may want to navigate from the entity to its process. 
Here’s a simple trick: add a ```processInstanceId``` field to your entity. No more searching with complex API queries—just follow the ID. 
<br/>
7. **Don’t blindly pass all variables into a Call Activity**
It’s tempting to tick the box that passes all variables from the parent to the subprocess. But it’s better to explicitly map only the variables you need. 
Otherwise, you risk data leaks or serialization issues. 
<br/>
8. **Configure history settings**
The more variables you have, the faster your history tables will grow. All BPM engines support history cleanup mechanisms—take time to configure them. 
If you need to keep historical data, create a mechanism to export it from the process DB to your own storage. 
Also, be mindful of sensitive data—like credentials or API keys. They might be safe during the process but later get dumped into history with all other variables. And history access might be less secure than the live process. 
So, to be safe—**avoid storing sensitive variables in history**. 
<br/>
9. **Use local variables where appropriate**
Technically, you can manage without local variables. But using them helps keep things organized. A clear local variable reduces the chance of errors. 
However, don’t overuse them. It’s not necessary to make every child context variable local—sometimes you need them to propagate downward. 
<br/>
10. **Avoid unnecessary variable shadowing**
Variable shadowing (redefining variables in nested contexts) is mostly useful in multi-instance activities. 
Outside of that, it's better to give variables unique names to prevent confusion. 
<br/>
11. **Document your variables**
BPM engines don’t manage variables, and IDEs typically don’t help with this either. 
Maintain your own variable registry—describe what each variable is for and where it's used. 
This will make your processes easier to maintain in the long run. 

## Conclusion 

Managing process variables with care is essential for building robust, maintainable business processes. By following these best practices, you can avoid common pitfalls and ensure your processes remain reliable and easy to support.  

Thoughtful variable management not only prevents bugs and performance issues but also makes your process models more transparent for everyone involved. In the end, a little discipline in how you handle variables goes a long way toward creating clean, predictable, and future-proof BPM solutions. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix Subscription Plans Update: Clearer Structure, More Value — Effective July 1st, 2025 ]]></title>
            <link>https://www.jmix.io/blog/jmix-subscription-plans-update-july-1st-2025</link>
            <guid>https://www.jmix.io/blog/jmix-subscription-plans-update-july-1st-2025</guid>
            <pubDate>Wed, 11 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/9396100_3013_Converted_Oblozhka_dlya_stati_v_blog_03_ea8a307367.png">Starting July 1st, 2025, we are introducing an updated subscription model for Jmix. These changes reflect the feedback we’ve gathered from long-term users and our ongoing efforts to keep Jmix sustainable and aligned with real-world development needs. ]]></description>
            <content:encoded><![CDATA[Starting **July 1st, 2025**, we are introducing an updated subscription model for Jmix. These changes reflect the feedback we’ve gathered from long-term users and our ongoing efforts to keep Jmix sustainable and aligned with real-world development needs. 

The new structure improves clarity across tiers, lowers the entry barrier for advanced features, and better separates distinct use cases like process automation. 

## What’s Changing — and Why 

1. **“Free” becomes “Community”**
We’re renaming the Free plan to **Community**. This name better reflects the open-source nature of Jmix and the tools shared across the entire developer base. No changes to features or access.

2. **“RAD” becomes “Sprint”**
While RAD served its purpose for many years, we’re renaming it to **Sprint** to better reflect how most teams work today — fast, structured, and iterative. The feature set remains unchanged.

3. **«Enterprise» becomes more focused and accessible**
With BPM functionality now separated, the Enterprise plan is focused entirely on enterprise-grade development features such as **Maps**, **Kanban**, **WebDAV**, **Notifications**, and **UI Constraints**. Following this restructuring, the plan will be priced **25% lower for companies** and **30% lower for individual developers**.

4. **«BPM» becomes a standalone plan** 
Process automation is a distinct application layer with its own architectural and operational needs. To better serve those use cases, we’ve moved all BPM-related functionality — including the engine, process forms, task panel, and admin tools — into a dedicated **BPM plan**, offered at the same pricing level as the former Enterprise tier. 

## A Note on Pricing Context 

Earlier this year, in **January 2025**, we introduced a moderate price adjustment to reflect platform growth and operating costs. **At that time**, the Enterprise tier included BPM and other advanced tools in a single bundle. 

With the July restructuring, we’ve realigned each tier to specific use cases. As a result, the Enterprise plan has a narrower focus, and its pricing has been revised accordingly. These changes are not simply discounts, but a reflection of the updated scope of each plan. 

## How These Changes Affect Existing Users 

- **Free (now Community)** continue to have full access to Jmix’s open-source core — now under a name that better represents its purpose. 
- **RAD (new Sprint) monthly subscribers** will see only a name change. Pricing and access remain unchanged. 
- **RAD (new Sprint) annual subscribers** will be automatically moved to the new Enterprise plan and will retain their current RAD pricing until **July 1st, 2027**. This includes full access to all Enterprise features (excluding BPM), including upcoming add-ons like Group Data Grid (coming Fall 2025) and Tabbed Application Mode. 
- **After the 2-year transition period**, these users will have the option to continue with **Enterprise at the standard rate**, or return to the **Sprint** plan. 
- **Enterprise subscribers** will be upgraded to the new **BPM plan** automatically. No action is needed. Access to all BPM features will continue uninterrupted and pricing remains the same. 

## Looking Ahead 

These updates are part of our continued effort to keep Jmix competitive, sustainable, and aligned with the needs of Java teams building complex enterprise software. The clearer tier structure also allows us to deliver new features faster and more predictably across the platform. 

We remain committed to helping you build and ship high-quality software — faster, with less overhead, and with tools that match the scale of your team. 


**Jmix — Develop smart, not hard!**

<style>
  ol {
    font-size: 18px;
    line-height: 1.55;
  }
  .jmix-website .blog-article__content ol li+li {
    margin-top: 8px;
}
</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Upgrade to Jmix 2: Future-Proof Your Projects]]></title>
            <link>https://www.jmix.io/blog/upgrade-to-jmix-2-future-proof-your-projects</link>
            <guid>https://www.jmix.io/blog/upgrade-to-jmix-2-future-proof-your-projects</guid>
            <pubDate>Tue, 27 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_v2_22a06d1767.png">This article explores why upgrading to Jmix 2 is a strategic move for your development projects.]]></description>
            <content:encoded><![CDATA[If you're still using Jmix 1, now is the perfect time to migrate to Jmix 2. Built on a modern, actively supported technology stack and packed with powerful new features, Jmix 2 offers significant advantages over its predecessor. This article explores why upgrading to Jmix 2 is a strategic move for your development projects, enhancing productivity, security, and user experience while future-proofing your applications.

## Modern Technology Stack for Enhanced Security and Performance

Jmix 2 is built on a cutting-edge technology stack, including Spring Boot 3 and Vaadin 24, which are updated with each Jmix feature release every four months. In contrast, Jmix 1 is tied to Spring Boot 2 and Vaadin 8, both of which are no longer officially supported. This means Jmix 1 is limited to critical bug fixes and select security patches, with some third-party dependency vulnerabilities unfixable due to incompatibility with newer versions.

With Jmix 2, regular dependency updates ensure your applications benefit from the latest security patches, reducing vulnerabilities and enhancing safety. Additionally, newer Java versions in Jmix 2 deliver improved performance and modern language features, enabling developers to write cleaner, more efficient code. This forward-looking approach ensures your applications remain secure, performant, and aligned with industry standards.

## Mobile-Friendly and Customizable UI with Vaadin 24

Jmix 2 leverages Vaadin 24 to deliver a mobile-friendly user interface out of the box. Unlike Jmix 1, which requires separate mobile applications or complex workarounds, Jmix 2 supports responsive layouts, allowing you to optimize your UI for mobile devices without additional development effort. This streamlines development and ensures a consistent user experience across desktops, tablets, and smartphones.

Moreover, Vaadin 24 provides greater control over your application’s look and feel. With direct access to DOM elements and straightforward CSS styling, customizing the UI is simpler than ever. Jmix 2 also includes Java wrappers for standard HTML elements like `div`, `span`, `p` and `hr`, making it easier to create tailored, visually appealing interfaces that align with your brand. Additionally, the frontend part of Jmix 2 is now based on the web components standard, significantly simplifying the integration of third-party JavaScript components and libraries, enabling developers to enhance their applications with a wider range of modern tools and functionalities.

## Enhanced Navigation and User Experience

Jmix 2 introduces standard browser navigation for opening views, aligning with familiar web browsing behaviors. Users can now open views in new browser tabs via the context menu and use deep links to access specific application views directly. For those who prefer the Jmix 1 approach of opening screens in internal tabs within a single browser tab, Jmix 2 offers the optional **Tabbed Application Mode** add-on, providing flexibility to suit different preferences.

## New Features and Improvements in Jmix 2

Jmix 2 introduces a range of powerful add-ons and functionalities that are absent in Jmix 1, empowering developers to build more sophisticated applications with less effort:

- **Kanban Add-on**: visualizes project workflows with a Kanban board component, using cards for tasks and columns for project stages.
- **Superset Add-on**: allows you to embed Apache Superset dashboards into your Jmix application views, enhancing data visualization capabilities.
- **UI Constraints Add-on**: manages UI component visibility and accessibility using declarative policies in resource roles, even for components not tied to the data model.
- **OpenID Connect Add-on**: simplifies external authentication with providers like Keycloak, mapping user attributes and roles to Jmix users seamlessly.
- **REST DataStore Add-on**: allows you to easily integrate external Jmix applications, accessing remote entities through the `DataManager` interface as if they were local, with full CRUD functionality.
- **Authorization Server Add-on**: provides authentication for REST APIs in compliance with OAuth 2.1, ensuring secure and standardized API access.
- **OpenAPI Integration in Studio**: configures OpenAPI client generators and automatically generates DTO entities, mappers, and services for integration with external REST APIs.
- **Data Repositories**: built on Spring Data, Jmix 2’s data repositories combine the simplicity of repository interfaces with advanced Jmix data access features like data access control, entity events and cross-datastore references.
- **Entity Comments**: lets you add comments to data model entities and attributes, improving documentation and collaboration.

Jmix 2 brings notable enhancements to existing features, streamlining development and improving usability:

- **Studio UI Preview**: unlike Jmix 1’s schematic previews, Jmix 2’s Studio shows views with real components and styles, closely mirroring the running application.
- **Hot Deployment Status**: a new icon in Studio indicates the hot deployment status of view controllers, descriptors, message bundles, and roles, keeping developers informed about the delivery of the latest changes in the source code to the working application.
- **UUIDv7 for Entity Identifiers**: Jmix 2 uses UUIDv7 for entity identifiers, significantly boosting database operation performance compared to Jmix 1.

## Closing the Gap: Grouping DataGrid Coming Soon

The only notable feature missing in Jmix 2 compared to Jmix 1 is the GroupTable. However, this will be addressed with the upcoming Grouping DataGrid, set for release in October 2025. Once implemented, Jmix 2 will surpass Jmix 1 in every aspect, making it the definitive choice for modern application development.

## Jmix AI Assistant and Growing Ecosystem

**Jmix AI assistant** is optimized for Jmix 2 development, offering superior guidance compared to Jmix 1. Additionally, Jmix 2 benefits from a rapidly expanding ecosystem of documentation, guides, learning courses, and code examples. Unlike Jmix 1, which is in maintenance mode with only critical updates, Jmix 2’s resources are continuously improved, providing developers with more comprehensive support. This growing knowledge base also enhances compatibility with third-party AI assistants, making Jmix 2 projects easier to develop and maintain.

## Future-Proof Your Development with Jmix 2

Jmix 2 is a dynamic, evolving platform that receives new features and improvements every four months, ensuring your applications stay current with the latest technologies. In contrast, Jmix 1 is in maintenance mode, receiving only critical fixes. By migrating to Jmix 2, you gain access to a modern, secure, and feature-rich framework that enhances developer productivity and delivers superior user experiences.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[One Framework, One Developer, Full Power: Ondrej’s Jmix Experience]]></title>
            <link>https://www.jmix.io/blog/one-framework-one-developer-full-power-ondrejs-jmix-experience</link>
            <guid>https://www.jmix.io/blog/one-framework-one-developer-full-power-ondrejs-jmix-experience</guid>
            <pubDate>Tue, 27 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Oblozhka_a241464ae5.png">This article shares the story of Ondrej, a senior Java developer, who accelerated full-stack development using Jmix.]]></description>
            <content:encoded><![CDATA[In the world of software development, finding tools that simplify the process without sacrificing functionality is a game-changer. Ondrej, a seasoned Java developer with over 20 years of experience, shares his journey of discovering Jmix and how it transformed his approach to building full-stack applications. His story highlights the challenges of traditional development and the advantages of adopting Jmix for solo developers and teams alike. 

![Ondrej, a seasoned Java developer, shares his journey of discovering Jmix and how it transformed his approach to building full-stack applications]({{strapiUrl}}/uploads/one_framework_one_developer_full_power_ondrejs_jmix_experience_2_9f3cf1c422.png)

 <h2 style="color:#342a98;">The Challenges of Traditional Full-Stack Development</h2> 

Ondrej’s career has been deeply rooted in Java, with extensive experience in both back-end and front-end technologies like React and Angular. However, he often faced significant hurdles when working on full-stack projects, especially as a solo developer or in small teams. 

- **Complexity**: Managing separate front-end and back-end stacks required extensive effort, from business analysis to deployment. 
- **Resource Constraints**: As a freelancer for the Czech Academy of Sciences, Ondrej often worked alone on administrative applications, where hiring additional help was impractical due to bureaucratic limitations. 
- **Time-Consuming Processes**: Older frameworks like GWT, which initially simplified his workflow, became obsolete and introduced slow build times (up to 5 hours for transpilation). 

 ![Картинка 3.png]({{strapiUrl}}/uploads/Kartinka_3_56322d9093.png)

These challenges led Ondrej to seek a more efficient solution — one that would allow him to focus on business logic rather than juggling multiple technologies. 

 <h2 style="color:#fc1264;">Discovering Jmix: A Turning Point </h2>

Ondrej was actively looking for a framework that would let him build full-stack applications using only Java. When he discovered Jmix, its modern approach and developer-centric features immediately caught his attention — it looked like the tool he’d been searching for. 

Key Benefits He Experienced: 

1. **Unified Development**: Jmix’s back-end-driven approach eliminated the need to worry about front-end security and state management, as the client side is inherently trusted. 
2. **Rapid Prototyping**: Using Jmix’s Figma component library, Ondrej could quickly create mock-ups and iterate with stakeholders before diving into development. 
3. **Speed of Development**: Building CRUD views and configurable applications became significantly faster, allowing him to deliver projects in weeks rather than months. 

![Картинка 4.png]({{strapiUrl}}/uploads/Kartinka_4_71b6827400.png)
 
 <h2 style="color:#7b6dff;">Real-World Applications: Success Stories </h2>

Ondrej has implemented several critical projects with Jmix, including: 

<strong>1. Czech Academy of Sciences – Economic Department </strong>
<div style="margin-left:20px;">
a.  A grant management system for 50+ institutions, handling requests, approvals, and PDF generation. <br/>
b. Supports 300 – 400 users with no performance issues, leveraging add-ons like Reporting and OpenID. 
</div>
<br/>
<strong>2. Scientific Evaluation System </strong>
<div style="margin-left:20px;">
a.  A large-scale application for evaluating thousands of scientific articles by international experts. <br/>
b.  Designed for 3,000 – 5,000 users, currently stress-tested with 1,000 active users ahead of its April launch. 
</div>
<br/>
For smaller projects, Ondrej notes that a 15 – 20 screen application can be built in just two weeks — a testament to Jmix’s efficiency. 

![Картинка 2.png]({{strapiUrl}}/uploads/Kartinka_2_4b3217a1e4.png) 

 <h2 style="color:#41b883;">Recommendations for Using Jmix</h2>

Based on his experience, Ondrej recommends Jmix for: 

- Freelancers and solo developers looking for an efficient and powerful development framework. 
- Large organizations needing rapid prototyping to validate business concepts quickly. 
- Internal business applications across industries, including banking, research, and corporate sectors. 

Jmix’s flexibility and ease of development make it a strong choice for a wide range of projects with a predictable number of users. 
 
![Картинка 6.png]({{strapiUrl}}/uploads/Kartinka_6_e497521d66.png)

 <h2 style="color:#25cde3;">The Future with Jmix </h2>

Ondrej plans to continue using Jmix for upcoming projects, particularly for internal company systems. His goal is to avoid the “front-end fatigue” of frameworks like React and Angular, focusing instead on solving business problems efficiently. 

His Advice to Other Developers:  
<div class="citata">
<div class="person-photo">
 
![Ondrej Gálik]({{strapiUrl}}/uploads/Obrezannaya_versiya_e09e641470.png)
 
</div> 
<div class="case__block">
<blockquote>
<h3>If you want to concentrate on business logic and avoid hunting pixels or debugging race conditions, Jmix is the way to go. It’s a powerful tool for freelancers, prototyping, and large enterprises looking for manageable solutions.</h3>
<p>Ondrej Gálik, Java developer</p>
</blockquote>
</div>
</div>


<style>
.citata {
display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background: #fafaff;
    border-radius: 16px;
    margin-top: 15px;

}
.person-photo {
    width: 140px;
}
.person-photo picture img {
    border-radius: 100%;
    height: 140px;
    margin-right: 40px;
    width: 140px;
    max-width: none!important;
}
.citata .case__block {
padding:0!important;

blockquote {
margin:0!important;
    margin: 32px 0;
    padding: 32px 32px 32px 82px;
    position: relative;
    width: 100%;
text-align: center;
p {text-align: center;}
}
blockquote::before {
    background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0zMS4yIDguODQ2VjRjLTcuNDY3IDAtMTMuNiA2LjE1NC0xMy42IDEzLjczdjYuODQ3QzE3LjYgMjYuNDYgMTkuMjIyIDI4IDIxLjA4IDI4aDYuNzQ2YzEuODU4IDAgMy4zNzQtMS41MzggMy4zNzQtMy40MjNWMTcuNzNjMC0xLjg4NS0xLjM0My0zLjMzMS0zLjItMy4zMzFoLTQuOGMxLjQ0LTMuMDM5IDQuNTEyLTUuMzIzIDgtNS41NTRaTS44IDE3LjczMXY2Ljg0NkMuOCAyNi40NiAyLjMxNiAyOCA0LjE3MyAyOGg2Ljc0OGMxLjg1NyAwIDMuNDc5LTEuNTM4IDMuNDc5LTMuNDIzVjE3LjczYzAtMS44ODUtMS43NDMtMy4zMzEtMy42LTMuMzMxSDYuNGMxLjQ0LTMuMDM5IDQuNTEyLTUuMzMgOC01LjZWNEM2Ljk3IDQgLjggMTAuMTU0LjggMTcuNzNaIiBmaWxsPSIjMzQyQTk4Ii8+PC9zdmc+);
    background-position: 50%;
    background-repeat: no-repeat;
    background-size: cover;
    content: "";
    height: 32px;
    left: 32px;
    position: absolute;
    top: 32px;
    width: 32px;
}
}
@media (max-width: 767px) {
blockquote {text-align:left!important;
p {text-align:left!important;}}
}
</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Nesting Java web apps in IFrames]]></title>
            <link>https://www.jmix.io/blog/nesting-java-web-apps-in-iframes</link>
            <guid>https://www.jmix.io/blog/nesting-java-web-apps-in-iframes</guid>
            <pubDate>Mon, 26 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/1200h630_4x_c164e848d3.png">What if you need to embed features from a Jmix, Vaadin, or Spring application into another website or web application? ]]></description>
            <content:encoded><![CDATA[What if you need to embed features from a Jmix, Vaadin, or Spring application into another website or web application? If your target platform isn't a portal system, the common approach is to use IFrame technology for this purpose. 

However, setting up IFrames today may not be entirely straightforward. 

When deploying outside your local PC, the application opened in an IFrame will likely require browser cookie support to function properly. Modern security standards dictate that cross-site cookie exchange only works when the following requirements are met: 

- Both the target site and the embedded application use a trusted HTTPS setup. 
- Session cookies have the Secure property enabled. 
- The SameSite property is disabled for these cookies. 

This means extra server configuration is required, even for testing or staging environments. 

As an example, we’ll use a server with the IP address 10.5.44.78, hosting both a Docker-based Jmix application and a static website that will be served with nginx frontend server configured for HTTPS. This could be run by a virtual server or a local virtual machine running a Linux-based OS. 

For production, you can purchase SSL certificates or use free options like Let’s Encrypt/ACME software. For testing purposes, we’ll set up fake domain names and map them to the server’s IP in the /etc/hosts file (located in Windows\System32\drivers\etc on a Windows PC). Add the following line to this file: 

```10.5.44.78 app.jmix site.jmix ```

After that, when you open ```https://app.jmix in browser```, it will send requests to IP-address we specified above.  

For easier access, you can also install a public SSH key (which you may need to generate first) on the remote server using the following command: 

```ssh-copy-id root@10.5.44.78``` 

## The website 

For this simple website, we won’t use any libraries or frameworks. Instead, we’ll write code that opens a browser-native dialog window when a link is clicked, embedding the IFrame contents. 

Place the following code inside a ```<script>``` tag in your HTML file or a separate JavaScript file: 

``` (function () { 
    let link = document.querySelector('a.app-link'); 
    link.addEventListener('click', (event) => { 
        event.stopPropagation(); 
        event.preventDefault(); 
        let dialog = document.createElement('dialog'); 
        dialog.style.width = '90%'; 
        dialog.style.height = '80%'; 
        dialog.insertAdjacentHTML('beforeend', ` 
           <iframe src="https://app.jmix/pub-page" frameborder="0" height="100%" scrolling="no" width="100%" allow="cookies"></iframe> 
        `); 
        document.body.appendChild(dialog); 
        dialog.showModal(); 
    }); 
})(); 
```

Then, add the corresponding ```<a>``` tag in your HTML markup: 

 ```<a href=”#” class=”app-link”>Open</a>```

This binds the dialog-rendering logic to a link with the class app-link, which triggers the modal when clicked. 

## The application 

Modern browsers restrict embedding content from one host into another without proper security configurations. 

The key security mechanism is the Content-Security-Policy header, specifically its frame-ancestors directive. This parameter specifies which hosts are permitted to embed your application. 

In Spring Boot-based frameworks like Vaadin or Jmix, you can configure this by adding a Spring Security configuration bean: 

```
import io.jmix.core.JmixSecurityFilterChainOrder; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.core.annotation.Order; 
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 
import org.springframework.security.web.SecurityFilterChain; 
 
 
@Configuration 
public class IFrameSecurityConfiguration { 
 
    @Value("${application.iframeancestors}") 
    String iframeAncestors; 
 
    @Bean 
    @Order(JmixSecurityFilterChainOrder.CUSTOM) 
    SecurityFilterChain anonChatbotFilterChain(HttpSecurity http) throws Exception { 
        http.securityMatcher("/pub-page").headers(headers -> { 
            headers.contentSecurityPolicy(csp -> csp.policyDirectives("frame-ancestors %s".formatted(iframeAncestors))); 
                }); 
        return http.build(); 
    } 
} 
```
 
This will give us the ability to specify allowed hosts in the application.properties file by defining the application.iframeancestors property value. If we set it as ```$IFRAME_ANCESTORS```, this value will be provided by a container management system like Docker Compose/Swarm or Kubernetes, or as a command line argument at application startup time. Using variables allows us to change configuration values without source code modifications or container rebuild. 

As Jmix - the framework we use - is targeted for enterprise development, all screens are allowed only to be used by authenticated users that have corresponding screen IDs in their role access lists. 

Since we specified the following URL address in the IFrame's src attribute: ```https://app.jmix/pub-page```, to have the application screen with the same URL we must create a View class annotated with both @Route("pub-page") and @AnonymousAllowed decorators. These will tell the framework to perform the required setup. 

Now we are ready to build the Docker container image. To do that, run the following command in a terminal opened in the project root directory: 
```
./gradlew -Pvaadin.productionMode=true bootBuildImage -imageName=sample-registry/app 
```

When build is successfully finished, we can create containers running configuration in docker-compose.yml file: 
```
services: 
  app-postgres: 
    container_name: app-postgres 
    image: postgres:latest 
    ports: 
      - "5432:5432" 
    volumes: 
      - postgres:/var/lib/postgresql/data 
    environment: 
      - POSTGRES_USER=app 
      # change this 
      - POSTGRES_PASSWORD=app 
      - POSTGRES_DB=app 
  app: 
    container_name: app 
    image: sample-registry/app 
    ports: 
      - "8080:8080" 
    environment: 
      - SITE_URL=https://app.jmix 
      - DB_HOST=app-postgres 
      - DB_USER=app 

      # change this 
      - DB_PASSWORD=app 
      - DB_PORT=5432 
      - DB_NAME=app 

              - IFRAME_ANCESTORS=site.jmix   
    depends_on: 
      - app-postgres 
volumes: 
  postgres: {} 
``` 

To make all these values applied to your Jmix or Spring application, replace hardcoded values with the variable names listed above in the application.properties file or create separate Spring profile configurations. 

To run this configuration, execute the following command in your terminal console: 

```docker compose -f docker/docker-compose.yml up –d ```

You can watch startup logs with the following command: 

```docker logs --tail -f app ```

## SSL-certificates 

To manage self-generated SSL-certificates without hassle, we install the mkcert console tool. It has distributions for all popular platforms. 

First, we must create a root certificate that will be used for SSL-certificate generation: 

 ```mkcert --install ```

Root certificates must be installed operating system-wide or imported in the browser to make generated SSL-certificates trusted. 

To generate SSL-certificates for the application server, run the following command: 

```mkcert -key-file /etc/nginx/ssl/mkcert/key.pem -cert-file /etc/nginx/ssl/mkcert/cert.pem app.jmix site.jmix 10.5.44.78``` 

We need also to install the root certificate and its key to a local PC. To do that install mkcert tool first. Then copy files from server to some local folder. 

Depending on the OS vendor, cert files placement may differ. To find it run mkcert command with CAROOT argument: 

```mkcert --CAROOT``` 

You may see output like below: 

```/root/.local/share/mkcert ```

A convenient way to upload or download files from the server is to use the command-line tool scp. To have it available on Windows operating systems, you may need to install Git Bash or PuTTY. 

The command to run on your local PC to download files from the server may look like this: 
```
scp root@10.5.44.78:/root/.local/share/mkcert/rootCA.pem C:\Users\user\AppData\Local\mkcert 

scp root@10.5.44.78:/root/.local/share/mkcert/rootCA-key.pem C:\Users\user\AppData\Local\mkcert 
```

The local mkcert path also depends on OS configuration. Run mkcert -CAROOT locally to determine it. 

When certificate files from the server are copied, run mkcert with the install argument locally: 

```mkcert --install ```

## Frontend-server  

To run a frontend-server that will serve the site and proxy requests to the application, install nginx packages on the server and create the following configuration: /etc/nginx/sites-available/10.5.44.78.conf 

``` 
upstream jmix-app { server 172.17.0.1:8081; } 
```

 ```
# app.jmix http configuration 

server {  

  listen 80; 

  server_name app.jmix; 
 
  location / { 
    proxy_pass http://jmix-app; 
    proxy_set_header Host $host; 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        
  } 

}  

# app.jmix https configuration 

server {  

  listen 443 ssl;  

  listen [::]:443 ssl;  

  ssl_certificate /etc/nginx/ssl/mkcert/cert.pem;  

  ssl_certificate_key /etc/nginx/ssl/mkcert/key.pem;  

  server_name app.jmix; 


  location / { 
    proxy_pass http://jmix-app; 
    proxy_cookie_path / "/; SameSite=None; HTTPOnly; Secure"; 
    proxy_http_version 1.1; 
    proxy_cache_bypass $http_upgrade; 
    proxy_set_header Upgrade $http_upgrade;  
    proxy_set_header Connection "upgrade"; 
    proxy_set_header Host $host; 
    proxy_set_header X-Real-IP $remote_addr; 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    proxy_set_header X-Forwarded-Host $host:443; 
    proxy_set_header X-Forwarded-Port 443; 
    proxy_set_header X-Forwarded-Server $host; 
    proxy_set_header X-Forwarded-Proto https;     
  }  
}  
 

# site.jmix configuration 

server {  

  listen 443 ssl;  

  listen [::]:443 ssl;  

  ssl_certificate /etc/nginx/ssl/mkcert/cert.pem;  

  ssl_certificate_key /etc/nginx/ssl/mkcert/key.pem; 

  root    /srv/site; 
 
  server_name site.jmix; 
 
  location / { 
     try_files $uri $uri/ =404;          
  } 

} 
```
 
Let's explain the most important parts of this configuration. 

The upstream configuration block: 

```upstream jmix-app { server 172.17.0.1:8080; } ```

defines IP address 172.17.0.1 as a source, which is used by Docker as the gateway to the external environment by default. 

The following valuable line: 
```
    proxy_cookie_path / "/; SameSite=None; HTTPOnly; Secure"; 
```
 
performs cookie configuration magic that is required for Vaadin/Jmix IFrame applications to be opened via IFrame embeddings. 

If you don't have access to frontend server configurations, try using these Spring configuration values: 

```
server.servlet.session.cookie.same-site=none 
server.servlet.session.cookie.secure=true 
```

The parameters ssl_certificate and ssl_certificate_key in the nginx configuration allow specifying SSL-certificate and its key file locations: 

  ```
ssl_certificate /etc/nginx/ssl/mkcert/cert.pem;  
ssl_certificate_key /etc/nginx/ssl/mkcert/key.pem; 
``` 

The root parameter specifies the website static files location: 

 ``` root    /srv/site; ```

 This can be just a single index.html file with the link and script contents we created at the beginning. 

The proxy set header lines: 

```
    proxy_set_header Upgrade $http_upgrade;  
    proxy_set_header Connection "upgrade"; 
```
 
specify configuration for WebSocket connections to be proxied. This protocol is used by Vaadin-based technologies for performant client-server data and command exchange. 

Don't forget to restart the nginx service after configuration changes for them to take effect, or even better, run the nginx -t command first to validate the configuration. 

When everything is up and running, we are ready to open the ```https://site.jmix``` URL in a browser, click the Open link, and see the IFrame with the application. 

 ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From Project to Scalable Product: Building Certikeeper with Jmix]]></title>
            <link>https://www.jmix.io/blog/from-project-to-scalable-product-building-certikeeper-with-jmix</link>
            <guid>https://www.jmix.io/blog/from-project-to-scalable-product-building-certikeeper-with-jmix</guid>
            <pubDate>Fri, 23 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/1920x1080_No_date_01a4773433.png">In this webinar, we show how Jmix helped turn a custom client project into Certikeeper — a scalable, multi-tenant compliance product — with full code ownership and rapid delivery.]]></description>
            <content:encoded><![CDATA[How do you turn a one-off client request into a scalable product for a regulated global industry? In a recent webinar, Edwin, my co-founder of AxiomaSoft, and I shared our startup journey building Certikeeper — a compliance and certification management solution for the food industry — using the Jmix platform.

## The Challenge: Food Safety Meets ESG Pressure

Certikeeper was born out of a real-world client need: managing complex food safety documentation and ensuring traceability in supply chains. But the challenges extended far beyond food. As Edwin and I have explained, ESG (Environmental, Social, and Governance) requirements are transforming supply chains across industries — from cosmetics to automotive.

Companies now face intense pressure to maintain transparent, audit-ready certification records. They must track carbon footprints, prove historical compliance, and support global regulations. This is where Certikeeper shines.

## Why Jmix?
The first iteration of the product was built with .NET. But the team quickly hit limitations — particularly with scalability, speed of development, and vendor lock-in. The switch to Jmix was a strategic decision.

<blockquote class="quote">
“With Jmix, we could deliver faster, own our code, and build exactly what we needed — no compromises,” is what I said back then.
</blockquote>

- Jmix’s multi-tenancy support, API tools, and modular architecture enabled the team to:
- Serve multiple clients from a single deployment
- Retain control of the source code
- Avoid escalating costs from proprietary platforms

## Key Takeaways from the Webinar

🚀 **From Custom to Product**

What started as a tailored project evolved into a reusable, multi-tenant SaaS platform. This kind of transformation is common for early-stage startups — and Jmix gave AxiomaSoft the flexibility necessary to adapt fast.

🔍 **Regulatory Complexity = Product Opportunity**

The food industry’s certification landscape is fragmented and non-transparent. Certikeeper centralizes data that would otherwise be scattered across standard registries. This transparency gap exists in many sectors, giving Certikeeper a path to expand beyond food. 

🌍 **ESG Is a Global Game**

Regulations aren’t just a European phenomenon. Global ESG compliance is reshaping how businesses think about software. Certikeeper helps clients manage cross-border certification demands and product passports.

💡 **Platform Ownership Matters**

One of the most powerful insights? Own your code. For startups, avoiding lock-in is essential. It provides strategic freedom, lowers risk, and makes the company more attractive to investors or acquirers.

🔗 **Seamless Integration Is Essential**

Certikeeper connects to clients’ ERP systems and certification authorities using APIs. The team is also developing a supplier-facing portal to make documentation sharing even easier.

🤝 **Real Talk for Founders**

The conversation wasn’t just technical. Edwin and Andrey talked honestly about stress, tough decisions, and lean execution. Their advice: Stay focused, iterate fast, and don’t promise what you can’t deliver.

## Why It Matters

This story isn’t just about one product — it’s a case study in how startups can thrive in compliance-heavy markets by making smart tech choices and staying flexible. For any founder trying to scale under pressure, this is a must-watch conversation.

Watch the full webinar to learn how Jmix helped ship Certikeeper fast — and why platform ownership is your startup’s greatest asset.

<iframe class="b-youtube-player" width="640" height="360" src="https://www.youtube.com/embed/x73sa66RCcI?si=w9-UM3oOKuhVDMwa" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

<style>.quote {
  position: relative;
  padding-left: 20px;
  border-left: 5px solid #ccc; 
  font-style: italic;
  color: #333; 
  line-height: 1.6; 
}</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Fast Prototype Consumer Facing App on Jmix]]></title>
            <link>https://www.jmix.io/blog/fast-prototype-consumer-facing-app-on-jmix</link>
            <guid>https://www.jmix.io/blog/fast-prototype-consumer-facing-app-on-jmix</guid>
            <pubDate>Tue, 13 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Online_Workshop_Making_Web_UI_1080e1920_Video_96873d3219.png">In this session, we will apply knowledge of layout specifics and CSS to create a new main view from scratch in order to give our application the look of typical social media.]]></description>
            <content:encoded><![CDATA[Jmix developers are backend developers, and one of the key advantages of Jmix is that they don’t need to use JS or TS to build web applications. However, many Jmix developers mistakenly assume they don’t need any frontend knowledge at all. While this might be true for internal apps, consumer-facing applications still require some frontend skills, especially CSS.

CSS can be complex and time-consuming, but there’s good news: starting from Jmix 2.x, working with CSS is much easier compared to Jmix 1.x.

In this workshop, we helped Jmix developers harness the power of CSS without the need to dive into stacks of books. Together, we applied layout techniques and CSS best practices to build a new main view from scratch, transforming our application into a social media-style interface.

During the first October webinar, Gleb Gorelov, Jmix Tech Lead, and Viktor Fadeev, Jmix Product Manager, discussed the theoretical aspects. In the next session, they demonstrated how quickly a consumer-facing app can be prototyped using Jmix. We're confident that you'll find this information extremely useful!

- How to implement custom CSS
- Creating custom app with specific CSS
- Useful resources for easy get go
- Q&A

You can watch the recording of the workshop on our <a href="https://www.youtube.com/live/roBa0Qb8R2E?si=FAERnYJNZ-qNLjKw" target="_blank">YouTube-channel</a>.

<iframe class="b-youtube-player" width="640" height="360" src="https://www.youtube.com/embed/roBa0Qb8R2E?si=FAERnYJNZ-qNLjKw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Build a Custom Project Management App in Java]]></title>
            <link>https://www.jmix.io/blog/how-to-build-custom-project-management-app-in-java</link>
            <guid>https://www.jmix.io/blog/how-to-build-custom-project-management-app-in-java</guid>
            <pubDate>Tue, 13 May 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/How_to_Build_a_Custom_Project_Management_App_in_Java_1080e1920_Video_6aa8a78612.png">In this webinar, we demonstrated how Jmix enables developers — even new to Java tech — to build a fully functional project management tool in minimal time.]]></description>
            <content:encoded><![CDATA[Even though many powerful project management tools exist, they can often be too complex, expensive, or restrictive for your specific needs. What if you could quickly build a custom project management solution that perfectly fits your workflow, requires minimal effort, and provides enterprise-grade security?

In this webinar, we demonstrated how Jmix enables developers — even new to Java tech — to build a fully functional project management tool in minimal time. Leveraging model-driven development, automatic UI generation, a configurable security system, and built-in reporting, you’ll see how easy it is to create a web-based alternative to Excel-driven project tracking.

Discover how Jmix can help you build custom project management solutions without the hassle of complex frameworks or expensive SaaS tools!

What you’ll discover:
- Typical requirements for project management apps.
- Tools we'll use in Jmix to build the app.
- How to visualize project timelines with a Gantt chart.
- How to track and allocate resources.

You can watch the recording of the workshop on our <a href="https://www.youtube.com/live/n7Cv7ixEUAU?si=2jFOcmWcsfF9LtGt" target="_blank">YouTube-channel</a>.

<iframe class="b-youtube-player" width="640" height="360" src="https://www.youtube.com/embed/n7Cv7ixEUAU?si=2jFOcmWcsfF9LtGt" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Deceptively Simple Exclusive Gateway]]></title>
            <link>https://www.jmix.io/blog/the-deceptively-simple-exclusive-gateway</link>
            <guid>https://www.jmix.io/blog/the-deceptively-simple-exclusive-gateway</guid>
            <pubDate>Mon, 07 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_PRO_49d245df6c.png">This publication begins a series of articles about the hidden nuances and pitfalls of BPMN 2.0. Despite the widespread belief that the notation is intuitive, in practice, its implementation in a process engine can present several surprises. ]]></description>
            <content:encoded><![CDATA[## BPMN: Beyond the Basics

This publication begins a series of articles about the hidden nuances and pitfalls of BPMN 2.0. Despite the widespread belief that the notation is intuitive, in practice, its implementation in a process engine can present several surprises. Analysts have it a bit easier: if something is unclear in the model, it can be written in comments or explained to the reader in words. Developers don't have that luxury – the engine requires precise instructions with zero ambiguity. Therefore, it’s important to understand exactly how each element works. 

Let’s start with the simplest one – the <b>Exclusive Gateway</b>.

At first glance, everything seems obvious: you place a diamond shape, draw arrows, and voilà! But what happens inside the engine? How does it choose the execution path? What if multiple conditions are met simultaneously? And supposing none of the conditions are fulfilled? In this article, we will address these questions and look at the specifics of implementing and using this element.

We will examine these using examples from Jmix BPM with the Flowable engine. Still, the principles are universal – BPMN 2.0 notation is consistent, and the core mechanisms for element operation are similar across all engines.

## A Familiar Concept, But Not Quite What You Think 

Everyone has dealt with flowcharts of algorithms. As you may recall, a diamond shape in a flowchart represents a conditional <b>IF</b> statement, with only two outcomes: <b>TRUE</b> or <b>FALSE</b>. It seems that this is why analysts and developers, when placing an exclusive gateway on diagrams, automatically phrase questions so that the answers are "yes" or "no." 

This is a mistake! Because of this school habit, BPMN models often become unnecessarily bulky, as authors try to model decision-making strictly within the "yes-no" logic.

In reality, an <b>Exclusive Gateway</b> is more like a <b>SWITCH</b> statement than an <b>IF</b> statement; it can have multiple outgoing paths:

![1.jpeg]({{strapiUrl}}/uploads/1_a7f1acbba6.jpeg)

Here’s how an Exclusive Gateway would look in code:

```
switch (forecast) { 
    case "rain" -> advise = "Take an umbrella"; 
    case "snow" -> advise = "Wear warm clothes"; 
    case "sunny" -> advise = "Wear sunglasses and sunscreen"; 
    case "windy" -> advise = "Hold onto your hat"; 
    case "storm" -> advise = "Stay indoors if possible"; 
    default -> advise = "Check the forecast for better advice"; 
}
```

There can be as many outgoing paths as needed – even 100 or more.  this might make the diagram harder to read, the engine handles it effortlessly! The process can function without any graphical representation at all.  

(Yes, that’s possible. You simply remove the section in the XML file that starts with the `<bpmndi:BPMNDiagram id="BPMNDiagram_process">` tag.) 

Let’s continue with our previous example. If we follow the <b>IF-ELSE</b> pattern, the question about rain with three possible answers would turn into this construction: 

![2.png]({{strapiUrl}}/uploads/2_a9adc7325f.png)

This seems a little bit complicated, doesn’t it? When looking at such a diagram, it's easy to lose focus due to the identical answers. The first <i>'Yes'</i> means it will rain, while the second <i>'Yes'</i> means it definitely won’t. Meanwhile, <i>'No'</i> indicates that it's uncertain, so rain might still happen. 

You can avoid the question entirely. Simply write clear continuation options on the outgoing flows, and you won’t have to sound like a person asking, “Could you please repeat the question?” – otherwise, it can be hard to understand the answer. For example, like this: 

![3.jpeg]({{strapiUrl}}/uploads/3_cc8317f802.jpeg)

## Those who divide, divide; those who unite, unite

The purpose of any gateway is not to ask questions but to manage the branching of the process. In other words, it allows the process to split into multiple paths, which may later converge – or not, as is sometimes the case.

Exclusive Gateways can serve as <i>'fork'</i> or <i>'join'</i> types in the process. A good practice is not mixing these roles, so let each gateway focus on one task. Unfortunately, it is quite common to see a single gateway performing both roles:

![4.png]({{strapiUrl}}/uploads/4_3f73a6d348.png)

<b>Never do this!</b> A gateway should only have one role. Don’t be greedy –place more gateways so it’s clear what each one is responsible for. 

![5.jpeg]({{strapiUrl}}/uploads/5_a683dddc38.jpeg)

Unfortunately, the notation doesn’t prohibit a gateway from having multiple incoming and outgoing flows. So even a complex structure like the one below will still work:

![6.jpeg]({{strapiUrl}}/uploads/6_73ed298be5.jpeg)

Is a <i>‘join’</i> gateway required after a <i>‘fork’</i> one? Not at all. The flow can simply end the process here if a condition is not met. There’s no need to drag an arrow across the entire diagram just to reach an end event. 

Can a gateway have only one outgoing flow? The notation does not forbid it, such a process will deploy and run fine. However, there’s no reason to do this, unless you are still working on the process and know that you will need a fork at this point but haven’t yet decided exactly how. 

![7.jpeg]({{strapiUrl}}/uploads/7_2f2cdc2776.jpeg)

## What’s Inside It?

Inside an <b>Exclusive Gateway</b>, there is nothing. That is, no properties or parameters can be set or configured. Nothing – just an <i>ID</i> and a <i>name</i>. When analysts write their questions above the diamond shapes on gateways, they essentially assign a text label to the element that has no effect on the process flow. 

For example, here: 

![8.png]({{strapiUrl}}/uploads/8_8e7d3bb063.png)

In the BPMN XML file, our gateway will look like this: 

`<exclusiveGateway id="Gateway_02z3qk1" name="Will it rain today?"/>` 

## About Conditions

Conditions are defined in the properties of the arrow, and they are not visible on the diagram: 

![9.png]({{strapiUrl}}/uploads/9_f44b80e85a.png)

The result of evaluating a condition must be a boolean value (<i>‘true’</i> or <i>‘false’</i>), otherwise an error will occur. 
```
${orderAmount > 1000} 
${price > 100 && price <= 500} 
${accountant.username == "jane"} 
```

How complex can a condition in a gateway be? Actually, the simpler, the better. However, if the logic is complex, it’s more efficient to package it in code and call the corresponding method in the condition like this: 

```${weatherService.getForecastCondition()}```

## How Does it Work?

The gateway doesn’t do anything – it has no internal logic. All the logic happens on the outgoing arrows (or, formally, the <i>sequence flows</i>). But don’t confuse the text label visible on the diagram with the condition checked by the engine.

![10.png]({{strapiUrl}}/uploads/10_ea3d5bd0fe.png)

When the process reaches the gateway, it looks at the outgoing flows and evaluates their conditions. Every textbook says the first condition that evaluates as true will determine the path the process takes.

Is it trivial? But what does <i>‘first’</i> mean? After all, the flows don’t have numbers. 

So how can we know? 

Let’s take a look at the XML file: 

```
<exclusiveGateway id="Gateway_18tv2av" name="Will it rain today?"> 
  <incoming>Flow_0hpfy8t</incoming> 
  <outgoing>Flow_1dxinb9</outgoing> (1) 
  <outgoing>Flow_1k36sg0</outgoing> (2) 
</exclusiveGateway> 
```

Ah, now it’s clear! The first outgoing will be `Flow_1dxinb9`, and the second will be `Flow_1k36sg0`. But how do we figure out which is which? 

Actually, it works differently. When the process reaches the gateway, the engine reads the list of outgoing flow IDs and starts looking for their definitions. The flow that is encountered first will be considered the first one. 

In fact, the flow definitions can be anywhere in the XML file, so there’s no requirement that they immediately follow the gateway. The elements in the model are arranged in the order they were created. When you edit a process intensively, adding and removing blocks and arrows, the XML becomes quite mixed up. But the engine doesn’t mind. 

Let’s return to our <b>Exclusive Gateway</b> and find the definitions of its flows. Here’s a life hack: if you give BPMN elements meaningful IDs, the model will be easier to read, and working with logs will be much simpler. 

For example:

```
<exclusiveGateway id="Gateway_is_rain" name="Will it rain today?"> 
  <incoming>Flow_incoming</incoming> 
  <outgoing>Flow_rain</outgoing> 
  <outgoing>Flow_clear</outgoing> 
</exclusiveGateway> 
<sequenceFlow id="Flow_incoming" sourceRef="startEvent1" targetRef="Gateway_is_rain"/> 
<sequenceFlow id="Flow_rain" name="Yes" sourceRef="Gateway_is_rain" targetRef="Activity_script_1"> 
  <extensionElements> 
    <jmix:conditionDetails conditionSource="expression"/> 
  </extensionElements> 
  <conditionExpression xsi:type="tFormalExpression">${forecast == "rain"}</conditionExpression> 
</sequenceFlow> 
<sequenceFlow id="Flow_clear" name="No" sourceRef="Gateway_is_rain" targetRef="Activity_script_2"/> 
```

Now it’s clear who’s first and who’s second. If we swap it, the processing order will change – the second will become the first and the first the second.

```
<exclusiveGateway id="Gateway_is_rain" name="Will it rain today?"> 
  <incoming>Flow_incoming</incoming> 
  <outgoing>Flow_clear</outgoing> 
  <outgoing>Flow_rain</outgoing> 
</exclusiveGateway> 
<sequenceFlow id="Flow_incoming" sourceRef="startEvent1" targetRef="Gateway_is_rain" /> 
<sequenceFlow id="Flow_clear" name="Нет" sourceRef="Gateway_is_rain" targetRef="Activity_1odfau0"> (1) 
  <extensionElements> 
    <jmix:conditionDetails conditionSource="expression" /> 
  </extensionElements> 
</sequenceFlow> 
<sequenceFlow id="Flow_rain" name="Yes" sourceRef="Gateway_is_rain" targetRef="Activity_0agmpfb"> (2) 
  <extensionElements> 
    <jmix:conditionDetails conditionSource="expression" /> 
  </extensionElements> 
  <conditionExpression xsi:type="tFormalExpression">${forecast == "rain"}</conditionExpression> 
</sequenceFlow>
```

<b>As seen in this example, while BPMN is a graphical notation, there are situations where you need to look at the code, as the diagrams cannot always be interpreted unambiguously.</b>

## Empty Condition Means "Yes."

You probably noticed that no condition is specified for the second outgoing flow. What do you think will happen in this case? 
 
If no condition is specified, it is considered true. In other words, when we swap the flow definitions, the engine won't even calculate the expression `${forecast == 'rain'}` it will simply follow the path labeled `’Flow_clear’`.

The developers often forget to set conditions on the outgoing flows from an Exclusive Gateway, causing the process to behave oddly – constantly veering in the wrong direction, even though the variable values are correct and logically it should be otherwise. Unfortunately, BPM engines like Camunda and Flowable do not check if conditions are set on outgoing flows during process deployment, so it can be hard to catch this error.

## Multiple Truths Are Possible 

Can multiple conditions be true at the same time? Clearly, yes. This follows directly from what we discussed earlier about the order of processing. The engine evaluates them sequentially, and the conditions are not related to each other. But only one will trigger. 

However, since it's difficult to control this order in practice, you'd have to check the XML each time, so it's better to make the conditions mutually exclusive. 

If you need to implement logic where multiple options could truly be triggered, you might want to consider an <b>Inclusive Gateway</b>, that handles this scenario. 

![11.png]({{strapiUrl}}/uploads/11_9f8ea354a0.png)

It’s also worth considering DMN decision tables, where you can implement almost any logic for choosing the appropriate option, even without writing code. 

In general, DMN is a powerful and greatly underappreciated tool, which we will discuss separately. 

## Default Flow

Of course, you know that it’s recommended to assign one of the outgoing flows as the default flow. Because if none of the conditions are true, the engine will throw an exception, and the process will stop. Therefore, it’s better to direct the process somewhere rather than having it fail due to an error. 

![12.png]({{strapiUrl}}/uploads/12_e9e697a8cb.png)

By the way, what happens if a condition is set on the default flow? Absolutely nothing, the engine will ignore it. 
On diagrams, the default flow is represented with a forward slash. 

In general, it’s exactly the same as with the switch statement. 

## Avoid Cascades 

Sometimes, there are several questions. And then, the urge is to put multiple gateways. But don’t rush! Take a close look – if there are no real splits on this path but rather just refining the answer by filtering out invalid options, you don’t need to create a cascade of exclusive gateways. Instead, you can write a more complex condition.

Here we see to gateways for evaluating atomic conditions `Sky == blue` and `Sea == green`. (To be a pedant, you’d write `sky.color == 'blue'`, but don’t care.) If both of them are true, the process goes further. But the model looks complicated.

![13.jpeg]({{strapiUrl}}/uploads/13_bb7b217275.jpeg)

As, for instance, here: 

![14.png]({{strapiUrl}}/uploads/14_2b0c5b99af.png)

## Let’s summarize:

1. An <b>Exclusive Gateway</b> contains no internal logic.

2. Its name is just for better understanding by humans and does not affect the engine.

3. The <b>Exclusive Gateway</b> can have as many outgoing flows as needed. It’s more like a <b>SWITCH</b> statement than an <b>IF</b> statement.

4. Avoid cascading <b>Exclusive Gateways</b> – formulate comprehensive conditions to avoid asking too many questions. 

5. Assign one outgoing flow as the default flow. 

6. Transition conditions are in the properties of outgoing flows and are not formally related. 

7. The engine does not check whether the conditions are mutually exclusive; they can be identical. This is the developer’s responsibility. 

8. The engine checks the conditions in the order in which the outgoing flows are listed in the XML file. 

9. As soon as one condition is true, the process moves along that branch, and the other conditions will not be checked. 

10. If no conditions are true, the default flow will be selected. 

That’s all for now! Now you’ve definitely got to know the <b>Exclusive Gateway</b>. Other BPMN elements also have their surprises, and we’ll continue to explore them in future articles. 

<style type="text/css">
ul.sm li:before {display: none;}
</style>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Unlocking the Potential of Jmix in Academia]]></title>
            <link>https://www.jmix.io/blog/unlocking-the-potential-of-jmix-in-academia</link>
            <guid>https://www.jmix.io/blog/unlocking-the-potential-of-jmix-in-academia</guid>
            <pubDate>Wed, 02 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Rezultat_2_8c861e77b0.png">In this webinar, we discussed the benefits of the Jmix Academic Program for professors, students, and academic enthusiasts.]]></description>
            <content:encoded><![CDATA[## Unlocking the Potential of Jmix in Academia: A Recap of Our Webinar

We recently hosted an insightful webinar exploring how Jmix supports the academic community — from professors and students to institutional innovators. Led by Viktoriia Klementeva, Community Manager, and Viktor Fadeev, Jmix Product Manager, the session highlighted the platform’s benefits, real-world use cases, and opportunities Jmix provides within the academic community.

For those who missed the session or wish to revisit key takeaways, this article summarizes the highlights of our webinar. You can now watch the full webinar on <a href="https://www.youtube.com/watch?v=Qb2SmGG--Gc" target="_blank">YouTube</a>.

<h2 class="purple">Jmix and Its Academic Journey</h2>

Since 2016 (originally as CUBA Platform), Jmix has provided **free academic licenses** to universities, helping educators cultivate skilled Java developers. Today, Jmix is used in **38 countries**, with over **200 licenses** issued to **70+ universities**. Our commitment remains unchanged: to make advanced technology accessible and empower future IT professionals.

![Map (1)1.png]({{strapiUrl}}/uploads/Map_1_1_749b09e82d.png)


<h2 class="purple">Who Benefits from Jmix?</h2>

Jmix is a versatile platform that serves multiple segments of the academic community:

1. <b>Professors:</b> Jmix enables educators to teach Java, Spring Boot, and Vaadin with a comprehensive development framework that facilitates real-world learning.

2. <b>Students:</b> The platform provides an intuitive environment for developing academic projects and final papers without the complexities of frontend development.

3. <b>Academic Enthusiasts:</b> Institutions can leverage Jmix to create applications that enhance internal workflows, such as library management and scheduling systems.


<h2 class="green">A Case Study: University Rey Juan Carlos</h2>

During our webinar, we discussed a real-world example from the University Rey Juan Carlos. A professor sought a Java-based solution to meet diverse academic needs, from database design to frontend development. Jmix stood out due to its open-source nature, rapid development capabilities, and ease of collaboration. As a result, the university successfully used Jmix in classes.

## Why Choose Jmix?

- **Cost-effectiveness:** Universities can create customized applications without significant development costs.
- **Ease of learning:** Clear documentation, AI assistance, and visual tools make Jmix accessible for beginners.
- **Efficiency:** Streamlined development allows users to focus on research and education rather than technical hurdles.
- **Collaboration:** The platform supports multi-user projects, fostering teamwork in academic research.
- **Customization:** Flexible workflows and external tool integration adapt to specific educational needs.
- **Future-proofing:** Built on Java and Spring Boot, Jmix ensures longevity and adaptability in evolving technology landscapes.

![2025-03-27_14-38-47.png]({{strapiUrl}}/uploads/2025_03_27_14_38_47_f6ab314fbb.png)

<h2 class="red">How to Get Started</h2>

1.  **Free Academic License:** Submit a request via our <a href="https://store.jmix.io/store/subscription/new/configure" target="_blank">portal</a> with proof of academic status.

2.  **Advanced Options:** Professors collaborating on large-scale projects can explore Enterprise solutions. Share your use case with us, and upon completion, contribute to the academic community by publishing your results.

3.  **Professor Training**
<div style="font-size: 18px;margin-left: 40px;">
Master Jmix with our <b>21-hour comprehensive course</b>, covering:

<ul class="sm" style="list-style: none;">
<li>a. Introduction to Jmix</li>
<li>b. Jmix Security Subsystem Basics</li>
<li>c. Accessing the data layer in Jmix</li>
<li>d. Working with files in Jmix</li>
<li>e. Jmix UI development</li>
</ul>
 
Integrate the course into your curriculum to teach Jmix confidently. If you would like more information about the course, please leave your contact information <a href="/academic-program/" target="_blank">here</a>.<br/>
</div>
 
4. <a style="font-size: 18px;" href="/certification/" target="_blank"><b>Certification</b></a>
 <div style="font-size: 18px;margin-left: 40px;">
Stand out with <b>Jmix Developer Certification</b>, available at a <b>special academic discount</b>. It is ideal for students and educators to validate their skills and boost career prospects.
</div>
<h2 class="green">Join the Academic Community</h2>

Jmix is more than a tool — it’s a partnership. We offer Slack <a href="https://join.slack.com/t/jmixplatform/shared_invite/zt-2juulpoaf-7yp7F~m_fhFDmZ6GXHr83A" target="_blank">channel</a>, <a href="https://forum.jmix.io/" target="_blank">forum</a>, and developer <a href="/services-support/" target="_blank">support</a> to ensure success.

<b>Watch the full webinar on <a href="https://www.youtube.com/live/Qb2SmGG--Gc?si=_mku7hwsR7Aedpni" target="_blank">YouTube</a> and connect with us at <a href="mailto:info@jmix.io">info@jmix.io</a> to learn more!</b>

<iframe class="b-youtube-player" width="640" height="360" src="https://www.youtube.com/embed/Qb2SmGG--Gc?si=_mku7hwsR7Aedpni" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

<style type="text/css">
	.green, .green a {
		    color: #41b883!important;
	}
	.red, .red a {
		color: #fc1264!important;
	}
	.purple, .purple a {
		color: #342a98!important;
	}
        .yellow, .yellow a {
                color: #fdb42b!important;
        }
ul.sm li:before {display: none;}
</style>


]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 2024 Recap and 2025 Roadmap]]></title>
            <link>https://www.jmix.io/blog/jmix-2024-recap-and-2025-roadmap</link>
            <guid>https://www.jmix.io/blog/jmix-2024-recap-and-2025-roadmap</guid>
            <pubDate>Wed, 19 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_recap_BLOG_6187cba114.png">2024 was the most fruitful year for content and learning materials creation. Jmix and the former CUBA Platform have always relied on detailed documentation, guides, and videos to deliver knowledge.]]></description>
            <content:encoded><![CDATA[## Looking back

2024 was the most fruitful year for content and learning materials creation. Jmix and the former CUBA Platform have always relied on detailed documentation, guides, and videos to deliver knowledge. Developers have said that CUBA Platform documentation could be used as a self-service learning course for software engineering. Now, developers can get even more, as we’ve delivered 3x times more technical content in 2024 vs 2023. Beyond that, the Jmix team launched 2 new <a href="https://www.udemy.com/user/jmix-team/" target="_blank">learning courses on Udemy</a> and rolled out <a href="https://ai-assistant.jmix.io/" target="_blank">AI Assistant</a>. We’re proud that Baeldung, as a respective learning resource for Spring developers, published a <a href="https://www.baeldung.com/jmix-rapid-web-application-development" target="_blank">tutorial about Jmix adoption</a>.

We aim to simplify the first steps and let developers with various skill sets easily access the technology whenever they need to build a business data app or a digital SaaS product. In 2025, we’ll continue intensively generating new feature-focused content and delivering sample apps to give you more ideas about implementing Jmix tech in real-life business cases. 

From a tech perspective, we’ve passed an important milestone - released Jmix Studio tools for consuming external REST API and rolled out a powerful <a href="https://www.jmix.io/marketplace/rest-datastore/" target="_blank">REST Data Store</a> concept. Both functionalities still need improvements, but significant tech decisions were made. Since Jmix 2.4, you can create distributed systems consisting of multiple interconnected Jmix applications with minimum effort. Generic REST API and REST DataStore add-ons enable developers to simplify data sharing across multiple applications, providing a seamless user experience when interacting with entities from different parts of the distributed system. If you still haven’t tested the REST DataStore functionality, follow <a href="https://docs.jmix.io/jmix/integrated-apps-guide/index.html" target="_blank">this guide</a> and find the new streamlined approach for building scalable and modular enterprise applications with Jmix.

In response to modern business requirements for the UI, we introduced brand new UI components: <a href="https://demo.jmix.io/ui-samples/sample/kanban" target="_blank">Kanban</a> and <a href="https://demo.jmix.io/ui-samples/sample/virtual-list-inline-editor" target="_blank">Virtual List</a>. Your apps may now deliver better interactive capabilities for team collaboration and mobile UI support. 

Progressive Web Applications (PWA) have become an option for business applications since the Jmix 2.x generation. There is no need to support various mobile platforms, learn new tech stacks, and have minimum maintenance effort across the installation base, as PWAs are still web applications optimized for the mobile experience. To assist Jmix developers with PWA development, @Mario David released a series of learning materials, including a <a href="https://demo.jmix.io/windturbines/icons/mobile-simulator/index.html" target="_blank">Wind Turbine sample app</a>, a <a href="https://www.jmix.io/blog/mobile-apps-with-jmix-2-and-vaadin-flow/" target="_blank">step-by-step guide</a>, and a <a href="https://www.jmix.io/blog/build-cost-efficient-mobile-business-apps-with-jmix-20-and-pwas/" target="_blank">technical whitepaper</a> covering the benefits and tradeoffs of building PWA business apps.

## Looking forward

While some open-source techs are switching back to proprietary (and back to open-source again), we remain consistent with our existing licensing model and deliver the Jmix framework under Apache 2.0. New business add-ons, bringing ready-made features, will be offered under a commercial license. Thus, there will be no changes. We remain confident in our current business model. Recently, <a href="https://www.jmix.io/blog/upcoming-pricing-changes-effective-january-1-2025/" target="_blank">we changed subscription prices</a> to compensate for inflation and cover the growth of associated expenses. Now, everything is balanced, and the team has resources for community support and product value growth.

### For newcomers

A simple-first approach to web development is gaining traction, and we expect that to continue in 2025. The promise of reduced complexity of modern Spring Boot development with Jmix remains actual and drives the growth of our community. Thus, we know newcomers may still face difficulties when adopting the technology. As we stay keen on democratizing Java and Spring Boot web development for software engineers, we will roll out new Jmix features in 2025, helping adoption and getting the first results faster. Here is the list of top 3 priorities:
- AI Assistant integration in Jmix Studio for better prompting involving your project context.
- Improved reverse-engineering feature supporting not only DB but also OpenAPI project generation.
- New view templates in Jmix Studio providing more enterprise layouts.

Our team was impressed by the support of the Jmix AI Assistant initiative, which now runs over 800 questions weekly—many thanks to all early adopters and testers. We continue working on integrating AI Assistant in Jmix Studio and improving the quality of answers. In the end, the Jmix developer will get a contextualized assistant in Jmix Studio who knows about the business domain of your project and can help you manipulate the code instantly. They say - English is the new coding language*) Imagine - you tell Jmix Studio you need a CRM project to manage custom software project sales with UI and press generate. After that, you review the project and make some modifications. Your CRM project is ready for demonstration. Combined with the unified Jmix project structure and powerful dev toolchain, it will look brilliant! This is a vector for our future Jmix Studio engineering effort, and we’ll try to bring this to life.

### For regular developers

We plan impressive improvements for regular Jmix developers. The top priority is developing the end-to-end testing tool, aka. <a href="https://github.com/jmix-framework/jmix-masquerade#readme" target="_blank">Masquerade 2.0</a>. The Jmix team intends to deliver this in the next Jmix 2.6 release and transfer all the Masquerade 1.0 capabilities. With this feature, we’ll close the missing item for producing high-quality software with Jmix. 

The next thing is the Jmix Studio feature named “Performance Tips.” We know it may be difficult for developers to anticipate how some Jmix framework configurations can affect the application in production. Thus, we decided to help developers avoid potential pitfalls by making some hints in the Jmix Studio about possible side effects on performance. Picture this. You make changes in the view descriptor of the list view and set the data loader read-only parameter to the false value. At this moment, Jmix Studio shows you a hint: “Well, this will let data context of the list view perform read and write operations every time you do manipulations in runtime. This may slow down the performance x10 times. Think twice!”. It will work like a guardrail for you. Sounds cool! 

Finally, we will improve the Jmix security subsystem, making it the best-in-class enterprise development platform supporting all top-popular security providers. It will include updates in the role designer tool and a new SAML integration add-on. The Jmix team understands that configuring enterprise security is a real challenge and can take up to 30% of total project development time. Thus, we want to make Jmix the most productive and easy-to-use tool to do this job with fewer errors and following best practices.

### For a better look and feel

Group Table is the missing gem in Jmix 2.x. It was a pivotal point for former CUBA Platform users when deciding to adopt the technology. In 2025, the Jmix UI team plans to deliver Group Data Grid and close the gap between Jmix 1.x and Jmix 2.x in terms of beloved by the community UI features. Group Data Grid will be reworked according to the Jmix Flow UI concept, but we promise to make it awesome.

As the community finds it valuable to build e-commerce solutions, adding the Card List UI component looks beneficial. It will automatically present items as thumbnails and improve the user experience when navigating the product or some digital asset catalogs.

Finally, we plan to add the Jmix Studio tool, which will allow us to simplify the integration of new JS components. We have already provided examples in the <a href="https://demo.jmix.io/ui-samples/sample/custom-component-js-library?tab=Description" target="_blank">UI Samples</a> and <a href="https://docs.jmix.io/jmix/flow-ui/vc/creating-components/js-component.html" target="_blank">documentation</a>. But it still needs a lot of boilerplate code to be written, and thus, it is not aligned with our <a href="https://www.jmix.io/alternative-to-low-code-platforms/" target="_blank">Less Code concept</a>*) The new tool will automatically generate boilerplate code, reducing developer effort and errors.

### For business

Business add-ons are crucial when building enterprise applications and evaluating the platform as part of the corporate platform engineering initiative. In 2025, we plan to improve <a href="https://www.jmix.io/marketplace/bpm/" target="_blank">BPM</a> and <a href="https://www.jmix.io/marketplace/reports/" target="_blank">Reports</a>, which are the top-rated business add-ons according to the 2024 statistics. In H1 2025, we’ll continue researching the enhancements list and announce it publicly in July 2025. 

We also plan to bring the Entity Relationship Diagram (ERD) tool as a Jmix runtime add-on. Our customer success team gets feedback that when users start working with Jmix BPM and Report runtime tools, it is difficult to manage the entity model structure without opening additional DB tools or Jmix Studio. With the ERD tool, users will observe the whole data model in the Jmix application runtime and implement new features much faster and with fewer errors.

### For platform engineering teams

We see a growing trend across large enterprises and development teams building Internal Developer Platforms (IDP). The main thing platform engineering is trying to accomplish is to offload the cognitive burden that developers meet while attempting to ship software. Surprisingly, this is the same as what Jmix is struggling for! In past years, platform engineering was primarily focused on DevOps, but recently, the scope was extended to the dev tools. 

Jmix capabilities can help developer teams standardize the dev tool sprawl in enterprise applications development, which are almost typical CRUD applications. In 2025, we’ll perform R&D to introduce a new Jmix IDP CLI concept. We plan to demonstrate a tool that will generate CRUD Jmix applications based on the OpenAPI file and DB schema without launching the IntelliJ IDEA. We’re experimenting with this feature and will keep you informed if we succeed. If you’re interested in this functionality, you can also send us a request to conduct a demo when it is ready or share your ideas.

### For CUBA Platform users

Previously, we <a href="https://www.jmix.io/blog/cuba-platform-end-of-the-free-maintenance-period/" target="_blank">announced that since March 2025</a>, the free support of the CUBA Platform would be switched to commercial support until the technology EOL. In 2024, we started helping our customers with assisting migration projects, and still, we see a considerable demand in this area. Estimating the effort needed to perform migration activities and some missing UI capabilities in Jmix 2.x, we understand that more time for transition is required. Thus, we decided to prolong the free support of the CUBA Platform until March 2026 with the continuation of free support on the forum. We plan to deliver one more update of the CUBA Platform until this time. Nevertheless, the Jmix team is mainly focused on evolving the Jmix 2.x technology, and we’ve got minimum resources for CUBA Platform support. Don’t hesitate to <a href="https://www.jmix.io/schedule-a-demo/" target="_blank">contact our sales team</a> to discuss possible migration strategies and consider using Jmix consulting services.

### Develop smart, not hard!
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar What’s new in jmix 2.5]]></title>
            <link>https://www.jmix.io/blog/webinar-what-is-new-in-jmix-2-5</link>
            <guid>https://www.jmix.io/blog/webinar-what-is-new-in-jmix-2-5</guid>
            <pubDate>Thu, 06 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Webinar_What_s_new_in_Jmix_2_5_1920x1080_05_33665f61bc.png">This webinar covered the new features and enhancements in the latest version of Jmix and our roadmap for future updates.]]></description>
            <content:encoded><![CDATA[Release Jmix 2.5 is here, and we are glad to share more details about key updates to this new version with you!

We recommend reading an article about the release and watching a webinar recording below to learn about all the features.

Speakers of the webinar:

Gleb Gorelov, Tech lead
Konstantin Krivopustov, Head of Engineering
Viktor Fadeev, Product Manager

What we discussed:

- Message Templates Add-on.
Create reusable, data-driven templates for emails and in-app notifications with an intuitive drag-and-drop editor.
- Tabbed Application Mode (Experimental).
Open views in separate tabs for a more desktop-like experience.
- Editing Objects on Maps.
Interact with and modify vector-based map elements directly in your app.
- Studio Enhancements.
Hot deploy indication, smarter debugging, improved UI styling, and OpenAPI client generation by tags.
- REST API & DataStore Improvements.
More flexible fetch plans and seamless remote file storage integration.
- UUIDv7 for Entity IDs.
Optimized for better database performance.
- Updated Dependencies.
Now powered by Spring Boot 3.4 and Vaadin 24.6 for improved security and performance.

You can see the recording of the webinar on our <a href="https://www.youtube.com/live/0dk5ziSY0SU?si=z1iM7jDeZOpj-MDJ" target="_blank">YouTube-channel</a>..]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 2.5 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-2-5-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-2-5-is-released</guid>
            <pubDate>Fri, 28 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/JMIX_2_5_da403b59d8.png">Overview of the new features and important changes of the Jmix 2.5 feature release.]]></description>
            <content:encoded><![CDATA[The Jmix team is pleased to announce the release of Jmix 2.5, which brings a variety of new features, improvements, and updates aimed at making development more efficient. This release focuses on enhancing productivity, expanding integration options, and introducing new application application features. For a detailed overview of all changes and upgrade instructions, visit the <a href="https://docs.jmix.io/jmix/2.5/whats-new/index.html" target="_blank">What's New</a> page in the documentation.

Here’s a brief look at the key features and improvements in Jmix 2.5.

## Message Templates Add-on

The Message Templates add-on provides a flexible and efficient way to manage and utilize reusable message templates within your Jmix application. It allows developers to define templates with placeholders, which can be dynamically populated with data at runtime. This add-on simplifies the creation of personalized messages such as emails or in-app notifications.

The message generation process leverages the widely-adopted **Apache FreeMarker** template engine. The system supports the creation of both HTML and Plain Text templates for maximum flexibility. The powerful **GrapesJS** web component has been integrated to provide a visual editor for crafting HTML templates. This editor enables you to construct templates using a library of pre-designed HTML blocks. You can easily design your templates by simply dragging and dropping these blocks from the palette onto the canvas.

![message-template.png]({{strapiUrl}}/uploads/message_template_be8b825dad.png)

The **Message Templates** add-on supports integration with other Jmix add-ons: Multitenancy, Email Sending and Notifications.

## Tabbed Application Mode

The **Tabbed App Mode** add-on, currently in an experimental state, lets you open application views in separate tabs within the main view. This provides a more integrated navigation experience and intended for building the desktop-like enterprise applications.

![tabbed-mode.png]({{strapiUrl}}/uploads/tabbed_mode_9ea7e9dcd9.png)

## Editing Objects on Map

The **Maps** add-on now supports selecting, moving, and modifying features added to vector sources. This makes it easier to interact with and edit map-based data directly within your application.

![map-edit.gif]({{strapiUrl}}/uploads/map_edit_5f9b487aa4.gif)

## Studio Improvements

### Hot Deploy Indication

Studio now shows an icon in the top right corner of files that support hot deployment, such as view controllers, descriptors, message bundles, and roles. This icon indicates the status of hot deployment, helping developers track whether their latest changes have been applied to the running application.

![hot-deploy.gif]({{strapiUrl}}/uploads/hot_deploy_41d98d61d6.gif)

### Application Log Analysis

Studio can now identify common exceptions in the application console and suggest ways to resolve them. This feature, combined with the hot deploy indicator, makes it easier to troubleshoot issues during development.

![analyze-log.png]({{strapiUrl}}/uploads/analyze_log_13c7797050.png)

### Jmix Run/Debug Configuration

A new Jmix-specific run/debug configuration has been added, replacing the standard Gradle configuration. This configuration ensures that the application shuts down smoothly without generating errors in the console, improving the development process.

![run-debug-config.png]({{strapiUrl}}/uploads/run_debug_config_becb45a9c0.png)

### classNames Editor and Autocompletion

Studio now offers better support for entering values in the `classNames` property of UI components. Autocompletion suggests available class names, and a visual editor in the Jmix UI component inspector makes it easier to select and apply class names.

![css-classes-editor.png]({{strapiUrl}}/uploads/css_classes_editor_bf21a518b6.png)

### OpenAPI Client Generation by Tags

When generating client code from an OpenAPI schema, you can now choose specific tags defined in the schema. Studio can also filter out schemas that are not used in the paths associated with the selected tags. This reduces the amount of generated code, making it easier to integrate only the necessary parts of the API.

![openapi-tags.png]({{strapiUrl}}/uploads/openapi_tags_f4ce905cd4.png)

## Advanced BPM Task List View

You can now generate an advanced BPM task list view using the *BPM: Advanced task list view* template in the view creation wizard. This view offers more features than the built-in *My tasks* view and can be customized to fit your project's needs.

![task-list.png]({{strapiUrl}}/uploads/task_list_c609d562ca.png)

## DataGrid Empty State

The `DataGrid` component now supports `emptyStateComponent` and `emptyStateText` properties, allowing you to display custom content when no data is available. This improves the user experience by providing meaningful feedback in empty states.

![data-grid-empty-state.png]({{strapiUrl}}/uploads/data_grid_empty_state_cffcd8e636.png)

## REST API and REST DataStore Improvements

**Generic REST** endpoints can now accept arbitrary fetch plans as JSON objects, in addition to named fetch plans. This makes it easier to integrate REST APIs and reduces the need for predefined fetch plans. Also, this feature greatly simplifies the usage of REST DataStore: you are no longer required to define all fetch plans in the shared repositories on both the client and service sides. Instead, you can employ inline fetch plans within your client views and Java code as you would normally do.

The **REST DataStore** add-on now includes a specific `FileStorage` implementation that works with files located in the remote application's file storage. This allows seamless integration with remote file storage systems.

## Using UUIDv7 for Entity Identifiers

Jmix 2.5 now by default uses **UUIDv7** for generating values for `UUID` attributes annotated with `@JmixGeneratedValue`. UUIDv7 is time-based, making it better suited for database keys due to its natural ordering. It is particularly beneficial for database indexing and query performance.

## Updated Dependencies

The Jmix 2.5 release includes updates to major dependencies:

- Spring Boot has been updated to version 3.4.
- Vaadin has been updated to version 24.6.

These updates ensure that Jmix continues to be built on a modern, secure, and performant foundation.

## Future Plans

The next feature release is expected in June 2025. We will focus on the following functionality:

- Integration of AI Assistant in Studio
- Production-ready Tabbed App Mode add-on
- SAML authentication add-on
- Switch (Toggle) UI component
- End-to-end UI testing library, similar to Classic UI Masquerade library

## Conclusion

Jmix 2.5 introduces a range of new features and improvements that enhance developer productivity, integration capabilities, and application features. We’re starting work on the next release, planned for June 2025, where we will continue to build on these improvements.

We invite you to join our <a href="https://forum.jmix.io" target="_blank">forum</a> and Slack channel to discuss these new features, share your experiences, and connect with the community. We also want to thank our community members for their valuable bug reports, pull requests, ideas, and suggestions—your contributions are what make Jmix better.

Stay tuned for more updates, and we hope you find Jmix 2.5 useful for your projects!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[JOIN THE MARCH JMIX ONLINE COURSE]]></title>
            <link>https://www.jmix.io/blog/join-march-jmix-online-course</link>
            <guid>https://www.jmix.io/blog/join-march-jmix-online-course</guid>
            <pubDate>Fri, 14 Feb 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/March_Jmix_online_course_1640h856_38fab9916c.png">We invite you to the March Jmix online course to learn Jmix in groups with a professional instructor!]]></description>
            <content:encoded><![CDATA[Spring is coming, and so is our <a href="https://forms.jmix.io/jmix-online-course-march?utm_source=blog&utm_medium=site&utm_campaign=online-course" target="_blank">new online course</a>!

We're thrilled to announce our upcoming paid Jmix course, where you'll gain comprehensive knowledge and hands-on experience. The feedback from students of previous online courses was **highly positive**:

“The course was a real marathon for both the master and the students.”

“Most of the information presented was highly relevant and practical, directly applicable to my work.”

“The instructor was very professional, and I am pretty sure of what he was explaining.”

**Course Details:**

**Dates:** 4 March - 1 April

**Schedule:** Three times a week on Monday, Tuesday, and Thursday

**Exact Dates:**

March: 4, 6, 10, 11, 13, 17, 18, 20, 24, 25, 27, 31

April: 1

**Format:** Online sessions via Zoom, with ongoing communication in a dedicated Slack channel

**Total Duration:** 39 hours (3 hours per day)

**Time:** 17:00 to 20:00 UTC+2

**Course Topics:**

- Jmix Application Deployment - 4 hours
- Data Manipulation - 14 hours
- Developing User Interface for Jmix Applications - 14 hours
- Access Control Subsystem - 7 hours

Homework is included as an additional practical part of independent work.

This is an excellent chance to boost your expertise and develop a firm grasp of Jmix.

If you'd like to be part of this group, please leave your contact details <a href="https://forms.jmix.io/jmix-online-course-march?utm_source=blog&utm_medium=site&utm_campaign=online-course" target="_blank">here</a>. 

Spots are limited, so we recommend reserving your place early!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Upcoming Pricing Changes Effective January 1, 2025]]></title>
            <link>https://www.jmix.io/blog/upcoming-pricing-changes-effective-january-1-2025</link>
            <guid>https://www.jmix.io/blog/upcoming-pricing-changes-effective-january-1-2025</guid>
            <pubDate>Tue, 17 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Pricing_post_4e82682884.png">We are announcing updates to Jmix Subscription Plan pricing, effective January 1, 2025. These adjustments reflect rising equipment, infrastructure, and labor costs, driven by global inflation, as we continue investing in the platform to deliver the best rapid enterprise application dev platform for Java developers.]]></description>
            <content:encoded><![CDATA[Dear Jmix Community,

We are announcing updates to Jmix Subscription Plan pricing, effective January 1, 2025. These adjustments reflect rising equipment, infrastructure, and labor costs, driven by global inflation, as we continue investing in the platform to deliver the best rapid enterprise application dev platform for Java developers.


## Updated Pricing

<table><thead>
  <tr>
    <th rowspan="2">Subscription Plan</th>
    <th colspan="2">RAD</th>
    <th>Enterprise</th>
  </tr>
  <tr>
    <th>Monthly</th>
    <th>Annual</th>
    <th>Annual</th>
  </tr></thead>
<tbody>
  <tr>
    <td>Company</td>
    <td>$ 110 → $ 119</td>
    <td>$1 080 → $ 1 149</td>
    <td>$1 800 → $ 1930</td>
  </tr>
</tbody>
</table>

- **Subscriptions for individual developers** will remain unchanged. We are committed to supporting solo developers and solopreneurs, leading innovation in enterprise application development.
- **Jmix Academic subscriptions** will continue to be free under our <a href="https://www.jmix.io/academic-program/" target="_blank">Academic Program</a>.

## How This Affects Current Users

- Existing subscriptions will maintain current pricing until their renewal date.
- Customers with active subscriptions can renew at the current rates until February 28, 2025.
- Special pricing agreements made before January 1, 2025, will remain valid for the agreed duration and developer seats.

## Committed to Empowering Our Community
We understand the challenges businesses face today and remain dedicated to providing a platform that helps you create business applications and internal tools in record time with minimum effort. Your trust and feedback inspire us to innovate and improve, ensuring that Jmix remains the best choice for the rapid development of modern Java enterprise applications.

Please <a href="https://www.jmix.io/contacts/" target="_blank">contact sales</a>, if you have any questions or need guidance on transitioning existing CUBA Platform projects, consultancy services, and training.

Thank you for being a valued part of the Jmix community.
Stay connected and be productive.

<style type="text/css">
	td, th {
		border: #11151b solid 1px;
                padding: 5px 10px;
	}
	table {
		border-collapse:collapse;
		border-spacing:0;
	}
</style>

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[New Jmix UI Course On Udemy]]></title>
            <link>https://www.jmix.io/blog/jmix-course-on-udemy-modern-frontend-with-java</link>
            <guid>https://www.jmix.io/blog/jmix-course-on-udemy-modern-frontend-with-java</guid>
            <pubDate>Tue, 17 Dec 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Udemy_Cover_Frontend_with_Java_692290a748.png">We are glad to announce the release of our latest Jmix course on Udemy "Modern Frontend with Java".]]></description>
            <content:encoded><![CDATA[We are glad to announce the release of our **latest Jmix course on Udemy <a href="https://www.udemy.com/course/frontend-with-java-and-jmix/?couponCode=3FC95D75BA5AD8FE7DFC" target="_blank">Modern Frontend with Java</a>**.

This course is a continuation and more advanced version of our **previous (free) course, <a href="https://www.udemy.com/course/rapid-application-development-with-jmix/" target="_blank">Rapid Application Development with Jmix</a>.**
The free course is dedicated to the basics of Jmix (working with Jmix Studio to streamline creating data models, DDL, UI Views, and business logic, understanding underlying technologies, and the basics of application security and deployment).

**Now, take the next step with this advanced UI-focused course!**

## What you’ll learn
- Learn the advantages and challenges of building frontend with Jmix
- Jmix Studio frontend tooling
- Building views, notifications, dialogs, and outcome logic for user actions
- Navigating views within the application
- Understanding the view lifecycle and handling events sequence on the view
- Purpose and use of facets
- Binding data to components, elements of components

## Who should join
- Java developers of all levels
- Teams looking to boost productivity
- Anyone interested in creating advanced UIs with open-source tools

By the end of the new course, you’ll have the skills to design and customize user interfaces for enterprise-grade applications.

<h2 class="red">SPECIAL PRICE OFFER 29,99$ <s>44,99$</s></h2>

To get a discount, use <a href="https://www.udemy.com/course/frontend-with-java-and-jmix/?couponCode=3FC95D75BA5AD8FE7DFC" target="_blank">the link</a> or a code `3FC95D75BA5AD8FE7DFC`

The course discount is available for a limited time only.

Enroll now and continue your Jmix journey!

<style type="text/css">
  .red {
    color: #fc1264!important;
    font-weight: 700;
  }

</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Simplifying Process Automation of Public Services: Develop smart, not hard]]></title>
            <link>https://www.jmix.io/blog/simplifying-process-automation-of-public-services-webinar</link>
            <guid>https://www.jmix.io/blog/simplifying-process-automation-of-public-services-webinar</guid>
            <pubDate>Tue, 19 Nov 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Workshops_BPM_Eng_afd3749cca.png">Discover how Jmix BPM empowers Java developers to quickly automate processes with BPMN 2.0 visual tools, seamless data and process forms creation, and zero BPM engine configuration effort.]]></description>
            <content:encoded><![CDATA[Adding an open-source BPM engine to your project is only the first step—it doesn’t mean you’re ready to automate complex workflows with user inputs, business logic, and handling data transactions.

Open-source BPM engines still leave you with challenges like managing data storage, building process forms, defining user assignment rules, implementing decision tables, and automating user interactions with the ability to fine-tune everything on the fly.

That’s where Jmix BPM makes all the difference.

Out of the box, Jmix BPM provides everything you need - so your team can quickly build process-driven applications without spending time integrating all the moving parts.

Attend the webinar to see how we will automate a demo process with Jmix BPM: “Registration and Approval Process for an Art Gallery Event.”

Agenda:

1. Open-source BPM engines overview
2. Steps to automate processes with an open-source BPM engine
3. Typical implementation problems and pitfalls
4. Jmix BPM Demo: Registration and Approval Process for an Art Gallery Event
5. Jmix BPM tech benefits and limitations
6. Q&A

You can see recording of workshop on our <a href="https://www.youtube.com/live/V30VMLkJdy8?si=CQ3iFXnX49vj8kDn" target="_blank">YouTube-channel</a>.

<iframe class="b-youtube-player" width="640" height="360" src="https://www.youtube.com/embed/V30VMLkJdy8?si=CQ3iFXnX49vj8kDn" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 2.4 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-2-4-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-2-4-is-released</guid>
            <pubDate>Fri, 01 Nov 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/JMIX_2_4_91b4a7367f.png">Overview of the new features and important changes of the Jmix 2.4 feature release.]]></description>
            <content:encoded><![CDATA[The Jmix team is announcing the release of Jmix 2.4, packed with new features designed to make your applications more interactive, flexible, and easy to integrate. This update introduces powerful add-ons and improvements that address different development requirements, from UI enhancements to integration capabilities. For a detailed overview of all changes and upgrade information, check out the <a href="https://docs.jmix.io/jmix/2.4/whats-new/index.html" target="_blank">What's New</a> page in the documentation.

Let's take a closer look at the key features of Jmix 2.4.

## Calendar Add-on

The new Calendar add-on provides a `FullCalendar` UI component based on the popular **FullCalendar** JavaScript library. The `FullCalendar` component  allows for different display modes such as day, week, and month. Users can interact with events by dragging events to reschedule them and resizing events to adjust their duration by dragging the edges.

![calendar.png]({{strapiUrl}}/uploads/calendar_667dd12a4e.png)

The FullCalendar component allows you to add different data providers, for example `ContainerDataProvider` to create calendar events from your JPA or DTO entities.

This feature allows developers to add a modern and highly functional calendar to their Jmix applications.

## PivotTable Add-on

The PivotTable add-on introduces a `PivotTable` component to the Jmix UI, powered by the **PivotTable.js** library. This component is perfect for data analysis and visualization, allowing users to:

- Create interactive pivot tables that summarize and explore data visually.
- Use drag-and-drop functionality to easily restructure and group data.
- Perform data aggregation with sums, averages, counts, and more.

![pivot-table.png]({{strapiUrl}}/uploads/pivot_table_63abd2ef3b.png)

With its intuitive UI, the PivotTable add-on makes working with complex data a seamless experience.

## Kanban Add-on

The Kanban add-on adds a visual project management tool to Jmix. Built on the **Smart Kanban** JavaScript library, this add-on allows users to track and manage their tasks effectively. Key features include:

- Customizable Kanban board that integrates easily with any Jmix view.
- Task management including user assignment, deadlines, and priorities.
- Stage management with columns to represent different phases of the workflow.
- Drag-and-drop support for easy task movement.
- Customization options for the appearance and behavior of the board.

![kanban.png]({{strapiUrl}}/uploads/kanban_79a3b3076d.png)

With this add-on, project workflows can be efficiently managed directly within your Jmix application.

## UI Constraints Add-on

The UI Constraints add-on allows developers to control the visibility and accessibility of UI components based on declarative policies defined in resource roles. This means that UI elements can be shown or hidden without writing code, based solely on user permissions. This makes implementing role-based UI control much simpler, saving developers time and enhancing security.

<img src="{{strapiUrl}}/uploads/ui_constraints_e285d34b11.png" width="756"/>

## REST DataStore Add-on

The REST DataStore add-on provides an easy way to integrate with external Jmix applications. External entities from a remote Jmix instance can be accessed through the `DataManager` interface, just like local entities. This means developers can display, update, and save data from remote applications seamlessly, without writing custom code for CRUD operations.

Examples of using this add-on can be found in the following guides:
- <a href="https://docs.jmix.io/jmix/2.4/integrated-apps-guide/index.html" target="_blank">Integrating Jmix Applications</a> 
- <a href="https://docs.jmix.io/jmix/2.4/separate-tiers-guide/index.html" target="_blank">Separating Application Tiers</a>

## Data Binding for HTML Components

HTML components such as `div`, `span`, and headers can now be declaratively bound to your data model entities using the `dataContainer` and `property` attributes in XML. This reduces the need for programmatically setting values in view controllers, simplifying your code and improving readability.

```xml
<layout>  
    <h3 id="nameField" dataContainer="departmentDc" property="name"/>  
    <div id="hrManagerField" dataContainer="departmentDc" property="hrManager"/>  
</layout>
```

## Fragment Renderer

Renderers for components like `virtualList` and `dataGrid` can now be defined using UI <a href="https://docs.jmix.io/jmix/2.4/flow-ui/fragments/fragments.html" target="_blank">fragments</a>. This means you can use fragments to customize how items are rendered, giving you greater flexibility in designing your UI.

The new `fragmentRenderer` XML element specifies the fragment Java class, for example:

```xml
<virtualList itemsContainer="usersDc">
    <fragmentRenderer class="com.company.onboarding.view.userfragment.UserFragment"/>
</virtualList>
```

An example of the fragment used as a renderer:

```xml
<fragment xmlns="http://jmix.io/schema/flowui/fragment">
    <data>
        <instance id="userDc" class="com.company.onboarding.entity.User">
            <loader id="userDl"/>
        </instance>
    </data>
    <content>
            <formLayout id="form" dataContainer="userDc">
                <textField id="usernameField" property="username" readOnly="true"/>
                <textField id="firstNameField" property="firstName"/>
                <textField id="lastNameField" property="lastName"/>
                <textField id="emailField" property="email"/>
            </formLayout>
        </hbox>
    </content>
</fragment>
```

The fragment renderer class should extend the `FragmentRenderer` base class with type parameters indicating the root component and rendered entity, for example:

```java
@FragmentDescriptor("user-fragment.xml")
@RendererItemContainer("userDc")
public class UserFragment extends FragmentRenderer<FormLayout, User> {
}
```

The `@RendererItemContainer` annotation is used to specify the data container that accepts the rendered entity.

## Asynchronous Tasks

The new <a href="https://docs.jmix.io/jmix/2.4/flow-ui/async-tasks.html" target="_blank">UiAsyncTasks</a> bean allows developers to run operations asynchronously using the current user's security context and then update the UI with the result. This lightweight mechanism, based on `CompletableFuture`, is perfect for simple asynchronous operations, complementing the more complex background task framework.

```java
@Autowired
private UiAsyncTasks uiAsyncTasks;

private void loadCustomersAsync() {
    uiAsyncTasks.supplierConfigurer(this::loadCustomers)
            .withResultHandler(customers -> {
                customersDc.setItems(customers);
                notifications.create("Customers loaded").show();
            })
            .supplyAsync();
}

private List<Customer> loadCustomers() {
    return customerService.loadCustomers();
}
```

## Search Improvements

Search functionality has been enhanced with the new `@ExtendedSearch` annotation, enabling "Starts with" searches for indexed fields. The updated `searchField` component allows users to open a search settings window to customize search strategies and result sizes, improving the flexibility of search operations.

![search.png]({{strapiUrl}}/uploads/search_71dae61130.png)

## Studio Component Inspector

The Jmix Studio component inspector now organizes properties into categories like **General**, **Data Binding**, **Size**, **Position**, and **Look & Feel**. This categorization makes it easier for developers to find the properties they need, enhancing productivity. Additionally, there is improved support for selecting icons using the `icon` property.

<img src="{{strapiUrl}}/uploads/component_inspector_e613d7cbc2.png" width="374"/>

## Studio Support for OpenAPI

Jmix Studio now offers enhanced support for OpenAPI integration, including configuration of the OpenAPI client generator and automatic generation of DTO entities, mappers, and intermediate services. These features simplify the integration of external REST APIs, making it easier for developers to work with external data sources.

![openapi.png]({{strapiUrl}}/uploads/openapi_103f474d99.png)

An example of using these features can be found in the <a href="https://docs.jmix.io/jmix/2.4/openapi-integration-guide/index.html" target="_blank">Integrating Applications Using OpenAPI</a> guide.

## Updated Dependencies

The Jmix 2.4 release includes updates to major dependencies:

- Spring Boot has been updated to version 3.3.
- Vaadin has been updated to version 24.4.

These updates ensure that Jmix continues to be built on a modern, secure, and performant foundation.

## Future Plans

The Jmix 2.4 release introduces new features that provide developers with additional tools for building applications. We’re already looking forward to the next release in February 2025. 

Our plans for the next release include the following:
- Completing the development of the Tabbed Main Window mode, which allows views to be opened in tabs within the main window instead of using browser tabs.
- Introducing a Message Templates add-on with a Flow UI, similar to the Email Templates add-on for Classic UI, but designed to be more flexible and accommodate a wider range of use cases.
- Adding the ability to edit elements of the map provided by the Maps add-on.

We will also collect feedback on the new features of Jmix 2.4 to make enhancements. This primarily relates to the experimental integration features: OpenAPI support and REST DataStore.

As always, we will dedicate significant time to bug fixing, minor feature additions, and performance improvements.

Our detailed roadmap for future releases is available as a <a href="https://github.com/orgs/jmix-framework/projects/23/views/1" target="_blank">GitHub project</a>. Patches for the current version 2.4 will be released approximately once a month to ensure regular updates.

We invite you to join our <a href="https://forum.jmix.io" target="_blank">forum</a> and <a href="https://join.slack.com/t/jmixplatform/shared_invite/zt-2juulpoaf-7yp7F~m_fhFDmZ6GXHr83A" target="_blank">Slack</a> channel to discuss these new features, share your experiences, and connect with the community. We want to thank our community members for their valuable bug reports, pull requests, ideas, and suggestions—your contributions are what make Jmix great!

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Architecting and Implementing Mobile Business Apps with Jmix 2 and Vaadin Flow]]></title>
            <link>https://www.jmix.io/blog/mobile-apps-with-jmix-2-and-vaadin-flow</link>
            <guid>https://www.jmix.io/blog/mobile-apps-with-jmix-2-and-vaadin-flow</guid>
            <pubDate>Thu, 31 Oct 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/PWA_2_3909a4fb66.png">In this blog post, we will explore how to build mobile business web applications using Jmix and Vaadin Flow.]]></description>
            <content:encoded><![CDATA[In this blog post, we will explore how to build mobile business web applications using Jmix and Vaadin Flow. In the <a href="https://www.jmix.io/blog/build-cost-efficient-mobile-business-apps-with-jmix-20-and-pwas/" target="_blank">first blog post</a> about this topic, we talked about the business reasons for creating cost-efficient mobile apps with Jmix and introduced the Jmix Wind Turbines example as one showcase of such an application. 

This time, we’ll dive into the technical aspects. First by focusing on how the latest features in Jmix 2.x and Vaadin Flow enable responsive and mobile-friendly business applications. Then, we will look at different architectural approaches to building mobile Jmix web applications. Finally, we will explore the technical details of the Wind Turbines project and how we implemented it.

## 1. Vaadin Flow and Mobile Responsive Layouts in Jmix

Vaadin Flow improved the support for responsive and mobile-friendly web application significantly over the previous generation of Vaadin: Vaadin 8. With the transition from Jmix 1.x to 2.x the new Vaadin generation: Vaadin Flow is used as the UI framework. This means that those improvements for mobile and responsive design are now available to Jmix developers. While Jmix 1.x relied on Vaadin 8, which required more manual handling of responsiveness using CSS and the “setResponsive” method, the introduction of Vaadin Flow in Vaadin 10 marked a shift toward more modern approaches to layout and design.

Since the introduction of Vaadin Flow in Version 10, there have been numerous enhancements that simplify mobile responsiveness, especially with the introduction of FlexLayout and improvements to HorizontalLayout and VerticalLayout, which now utilize the CSS Flexbox model. This has made it much easier to create layouts that adapt dynamically to different screen sizes without requiring extensive custom CSS. Flexbox-based layouts allow components to resize, align, and adjust spacing automatically, ensuring that applications work seamlessly across various device types.

Some layout components like the FormLayout in Vaadin Flow / Jmix 2.x are already mobile optimized by default. This means that forms built with FormLayout dynamically reorganize fields into a grid-like structure with one or more columns, optimizing the display across different devices without needing additional customization. 

Other UI components like the DatePicker or the select component adapt their behavior based on the device type, to provide an optimal user experience when used on touch devices as well as when used with a mouse on a larger screen. 
Finally, Vaadin Flow offers utility classes that simplify responsive design by enabling developers to show or hide elements based on the viewport size. These advancements help developers to build Progressive Web Apps (PWAs) that are mobile-optimized and responsive with less effort in Jmix 2.x, compared to the manual techniques that were common in Jmix 1.x.

Further Information 
- <a href="https://vaadin.com/blog/building-responsive-websites-with-java-and-vaadin-flow" target="_blank">Building Responsive Websites with Java and Vaadin Flow</a>
- <a href="https://vaadin.com/blog/building-responsive-layouts-with-vaadin-utility-classes" target="_blank">Building Responsive Layouts with Vaadin Utility Classes</a>
- <a href="https://vaadin.com/docs/latest/components/form-layout" target="_blank">Form Layout in Vaadin 24 Documentation</a>
- <a href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/" target="_blank">A Guide to Flexbox - CSS Tricks</a>

## 2. Architectural Options for Building Mobile Web Apps with Jmix 

Before diving into the technical details of how to utilize the Improvements from Vaadin Flow, when building a mobile web application, there are also some architectural considerations to think about. In this section we will investigate the different options we have when it comes to coming up with a solution architecture for a mobile web application with Jmix. 

Each approach comes with its own set of trade-offs, offering specific benefits and challenges depending on the project requirements. In this section, we’ll explore three common strategies for mobile web app development with Jmix, each suited to different needs in terms of complexity, scalability, and development speed.

### Option 1: Unified Jmix Application with Responsive Mobile Views

The first approach is to adapt an existing Jmix business application by making its views responsive for mobile devices. With the features provided by Vaadin Flow, such as out-of-the-box responsive layouts, it’s easier than ever to create mobile-friendly interfaces within your existing Jmix app.
 ![12.png]({{strapiUrl}}/uploads/12_308c91e926.png)
This approach is particularly useful when the mobile web app needs to offer a large portion of the same functionality as the desktop application. By utilizing responsive design and reusing existing components, you can efficiently deliver a Progressive Web App (PWA) without creating a separate mobile application. 

It also allows you to progressively optimize views for mobile use while keeping everything within the same codebase. For example, you can start by using mobile-friendly out-of-the-box components like FormLayout, which require minimal effort to become fully responsive. From there, you can incrementally enhance other views, such as List Views or custom views, for a seamless mobile experience. 

This approach also offers flexibility in how you handle mobile optimization. Developers can choose to route mobile users to dedicated views specifically optimized for mobile devices, or they can apply responsive design techniques to ensure the same view adapts across different devices. When comparing the solution to the next option the outcome for the end user might be the same. The main difference is that in this unified approach, all views live within the same application, minimizing architectural complexity while delivering a mobile-optimized user experience.

### Option 2: Dedicated Mobile Web App with Jmix and Separate (Jmix) Backend 
If you want a clear architectural separation between your mobile user experience and the back-office system, building a dedicated mobile web app with Jmix can be advantageous. This approach is useful in scenarios where the mobile app is intended for a different user group or requires a completely different design or layout from the back-office interface. It could also be necessary to have such a separation due to security restrictions. 
![10.png]({{strapiUrl}}/uploads/11_d0d8e37a21.png)
In the Wind Turbines example, a dedicated mobile web app could be a good choice if the fieldworkers are external partners, such as subcontracted companies, who only need access to a small, well-defined subset of the data and functionality.   

This streamlined mobile web app would feed into a larger, more complex business process within the company’s internal systems. For example, once an inspection is submitted by a fieldworker, a BPMN process could be triggered in the back-office system. This process could involve additional approvals, notifications to customers, or internal follow-ups. By separating the mobile app from the back-office system, you can create a bounded context that ensures the mobile app handles only the necessary tasks while integrating with the broader business logic. In this bounded context the data model could be a small subset or even different from the back-office system, as it only needs to represent the needs of the mobile use-cases.  

Another benefit of this separation is that oftentimes different authentication schemes apply for different user groups. For instance, the external fieldworkers might authenticate using the built-in username and password functionality from Jmix, while internal users accessing the back-office system might rely on an enterprise-wide SSO solution (like Okta, Microsoft Azure AD etc.) that is not exposed to third parties. 

By decoupling the mobile frontend from the backend, this architecture supports a more flexible and modular design. However, it also introduces the complexity of managing multiple systems and distributed computing in general. A dedicated Mobile Web App built with Jmix can either function purely as a presentation or UI layer, or it can be a full-stack application with its own persistence layer. In the first case, the mobile app acts as a thin client, interacting with a backend system (like a Jmix-based back-office) purely via REST APIs. This keeps the mobile app lightweight, as it does not manage any data storage directly, relying entirely on the backend for all persistence and data retrieval.  

Alternatively, the mobile app can be a full-stack Jmix application with its own database, handling persistence independently. This option offers greater flexibility, as it allows the app to store data optimized specifically for mobile use cases or to maintain additional information that may not be relevant to the back-office system. However, it requires establishing a data synchronization mechanism between the mobile app and the back-office system, whether through asynchronous synchronization or by forwarding the data changes synchronously to the back-office system when the data is changed in the mobile web app. Storing the data persistently on the mobile web app increases resilience due to temporal decoupling—the mobile app can continue functioning even if the back-office system is temporarily unavailable. 
![11.png]({{strapiUrl}}/uploads/9_22aa7f548b.png)
Whether to choose a thin client approach or a full-stack application depends on the specific project requirements and the balance between flexibility and complexity. Jmix supports both, the thin client as well as the dedicated full stack application approaches. In the following section, we’ll explore how Jmix’s new REST Datastore in Jmix 2.4 makes the thin client approach very easy to achieve, where the mobile app functions without its own persistence layer and interacts with the backend through REST.  

#### Leveraging the REST Datastore in Jmix 2.4
A key feature introduced in Jmix 2.4 is the REST Datastore, which simplifies the interaction between the mobile app and the backend in case the backend is also built with Jmix. With the REST Datastore, developers can use Jmix’s built-in UI components and data binding mechanisms as they normally would, but instead of interacting with a local database, the data is fetched and saved via REST APIs from a remote Jmix backend.

This eliminates much of the boilerplate code typically needed for manual REST API interactions. Instead of writing custom code to send requests, handle responses, and map data between the mobile web app and backend, the REST Datastore abstracts these operations. Jmix handles the underlying REST communication seamlessly as long as the backend application also uses Jmix and exposes the API via the generic <a href="/marketplace/rest-api/" target="_blank">REST API add-on</a>.

### Option 3: Dedicated Native or Web App with Jmix as Backend
The third architectural option involves building a dedicated frontend using technologies like React, Vue, or Angular, while Jmix serves exclusively as the backend. In this model, the mobile web app interacts with Jmix through REST APIs rather than using Vaadin Flow for the UI. 

 ![9.png]({{strapiUrl}}/uploads/10_9ee81254d6.png)

One important aspect with Vaadin Flow is its communication architecture between the browser and the server, which relies on frequent HTTP interactions. Most of the UI interactions, like button clicks trigger server-side logic. While this transparent communication simplifies the programming model for many business applications, it requires a reliable internet connection to maintain the constant interaction between the browser and server. This can be a limitation for mobile web apps in environments where network connectivity is intermittent or slow, as interruptions can affect the user experience. In case this becomes a problem, a looser coupling between frontend and backend becomes advantageous. In this setup, the frontend is entirely client-side, and the server only handles stateless requests via REST APIs. This architecture is better suited for offline capabilities, where the app can continue functioning and synchronize with the backend once connectivity is restored. 

By using Progressive Web App (PWA) technologies or frameworks like React Native, developers can create highly responsive mobile web apps that offer a more seamless experience in low-connectivity environments. 

While this option provides greater flexibility, it is traditionally more complex to implement. Separate frontend and backend codebases require additional maintenance and building a fully stateless mobile web app demands more initial setup compared to the other Jmix-based options. However, for projects that prioritize customization, offline support, or need a more disconnected architecture, this is often the most suitable choice. Also, the existing knowledge within the team plays a crucial role. In case your team has dedicated front-end experience, it can also be beneficial to consider this option.

### Choosing the Right Architectural Approach for Your Mobile Web App

Option 1 is our recommended option for teams that are just starting to build mobile web applications with Jmix but also for projects where maintaining a simple, unified architecture is critical. It’s ideal when there isn’t the need or ability to manage multiple deployment units, as in a microservices-based architecture. 

It was also chosen for the Jmix Wind Turbines project because of its simplicity and the focus on demonstrating the speed of development with Jmix. 

Option 2 is preferable if you want to decouple your mobile web application from your back-office application for one of the mentioned reasons. It brings some additional complexity in exchange with the gained flexibility, but still leverages the development speed and convenience from Jmix 2.x / Vaadin 24 for the mobile web app.

In case the characteristics of the Vaadin Flow architecture are not enough or there are very specific UI / UX requirements that are not easily achievable with Vaadin, then Option 3 might be the best option. It is the most costly in terms of development efforts and requires skills in the selected technology, but it also brings the freedom to choose the exact technology that fits the specific needs. Jmix in this case acts as the backend that provides access to the data model via REST API, authentication and authorization and potentially back-office functionality like BPMN engine etc.

By using one of these architectural approaches, you can tailor your mobile web app development to suit the specific needs of your project. A unified Jmix application is ideal for quick and cost-effective solutions, while dedicated mobile web apps provide more flexibility and scalability when mobile-specific requirements are a priority.

## 3. Technical Implementation of the Jmix Wind Turbines

After investigating the Jmix 2.x and Vaadin improvements and discussing the architectural options for mobile application, we will now get more concrete and see how to apply these various improvements in more detail. 

As mentioned above, the Jmix Wind Turbines example uses the architectural option 1 which combines the mobile UI and the back-office application into one deployment artifact.

In this section we will cover different aspects of the Wind Turbines implementation: how to enable PWA functionality, the use of mobile optimized Vaadin components like “VirtualList”, leveraging and adapting Jmix view generation for mobile use, and customizing styles to create a good look & feel on a mobile device.

### Enabling PWA Functionality

To enable PWA functionality in your Jmix application, you use the @PWA annotation from Vaadin. Every Jmix application has this annotation already active by default when a new project is created via Jmix Studio. 
This annotation transforms your web application into a Progressive Web App (PWA), which can be installed on a user’s device, providing an app-like experience. The @PWA annotation includes multiple configuration options such as ```name, shortName, backgroundColor```, and ```display```, which influence the look & feel of the installed PWA.
In the Jmix Wind Turbines application, the PWA functionality is added to the application class:
```
import com.vaadin.flow.component.page.AppShellConfigurator;
import com.vaadin.flow.component.page.Push;
import com.vaadin.flow.server.PWA;
import com.vaadin.flow.theme.Theme;

@Push
@Theme(value = "jmix-windturbines")
@PWA(name = "Windturbines", shortName = "Jmix WT", backgroundColor = "#235FD5", display = "standalone")
@SpringBootApplication
public class JmixWindturbinesApplication implements AppShellConfigurator {
    public static void main(String[] args) {
        SpringApplication.run(JmixWindturbinesApplication.class, args);
    }
}
```
The display attribute defines how the web app is presented on the mobile operating system. There are four main modes:
Standalone and fullscreen modes are designed to run the app in its own window, separate from the browser. In these modes, browser UI elements like the address bar and navigation are hidden, creating a focused, immersive interface. This is particularly suitable for applications that are supposed to look very close like a native application. Fullscreen mode goes a step further by using the entire screen, which is normally not common for business applications. When using standalone / fullscreen it is important that the app itself has properly built-in navigation capabilities

<div class="mobile-screenshot">

<img src="{{strapiUrl}}/uploads/pwa_windturbines_standalone_c7b028a983.jpeg" alt="pwa-windturbines-standalone">

</div>

Minimal-UI mode is similar to standalone mode but retains some browser UI elements like the address bar, which cannot be typed into. This mode is useful for applications that require some browser features like browser refresh or the back button, providing a balance between a full browser experience and a standalone app. It is beneficial for simple web pages that need basic browser functionalities.
Browser mode, on the other hand, makes the app behave like a regular web page within a browser tab, retaining the full browser UI. This mode is best for content that requires extensive navigation or multi-tab support, such as news websites or blogs. This mode also does not create a dedicated application in the App switcher of the operating system. This means that to switch between the application and a regular website in your browser, you must use the switch tab functionality of the browser.

<div class="mobile-screenshot">

<img src="{{strapiUrl}}/uploads/pwa_windturbines_minimal_ui_51323a9427.jpeg" alt="pwa-windturbines-minimal-ui" class="mobile-screenshot">

</div>
 
Although the PWA specification defines all those display modes, not all operating systems support them (yet). For iOS e.g. it only supports “standalone” and “browser” modes with fallbacks for the other modes. 
For the Jmix Windturbines app, we use the standalone mode, which is also the default setting from Vaadin’s @PWA annotation.

### Optimizing Mobile Data Views via Card Layout

In Jmix applications, list views are typically generated using DataGrids. While they are efficient for desktop views, they are not optimal for mobile interfaces due to the horizontal scrolling required to view multiple columns. Representing a list of items on mobile is typically done by displaying each item underneath the other.

Using a card layout improves the user experience on mobile devices. It organizes information into distinct, easily readable sections that fit well within the vertical space of a mobile screen. This layout is technically supported by Vaadin’s VirtualList, allowing for the creation of a dynamic, responsive UI.

To create a more mobile-friendly interface, you can start with a standard CRUD UI and then replace the DataGrid with the ```<virtualList />``` XML tag. The data binding is the same as for DataGrid. The difference is that instead of defining a set of columns to render, you define a handler function that returns a component to be displayed for each item.

Let’s explore how we used the VirtualList component for the Turbine List View. Here is the XML view descriptor:
```
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<view xmlns="http://jmix.io/schema/flowui/view"
      title="msg://turbineListView.title"
      focusComponent="turbinesVirtualList">
    <layout spacing="false" padding="false">
        <!-- ... -->
        <vbox classNames="layout-body" width="100%" height="100%" padding="false" spacing="false">
            <vbox width="100%" classNames="light-background" padding="false">
                <scroller width="100%" height="100%">
                    <virtualList id="turbinesVirtualList"
                                 width="100%"
                                 height="100%"
                                 itemsContainer="turbinesDc"
                                 alignSelf="CENTER">
<fragmentRenderer class=" io.jmix.windturbines.view.turbine.TurbineCard"
                                 />
	</ virtualList >
                </scroller>
            </vbox>
        </vbox>
    </layout>
</view>
```
We use the ```<virtualList />``` tag to create a virtual list and bind it to the turbinesDc data container. 

Now, there are two approaches to display each turbine instance within the list:
*1. Using Fragment Renderer (New in Jmix 2.4)*
In Jmix 2.4, you can declaratively specify a fragment to render each list item using the FragmentRenderer. This approach simplifies the process by automatically binding the data to the fragment’s instance container. In the above XML, the fragmentRenderer points to a TurbineCard fragment, which encapsulates the UI and logic for displaying a turbine’s details.

The data binding is handled by Jmix, and we simply configure how to display the turbine details declaratively. This method works well if you don’t need to inject dynamic content into the fragment at runtime.

*2. Programmatic Rendering with the Fragments API*
Alternatively, if your use case requires more dynamic handling, such as injecting additional parameters or handling callbacks, you can define a custom renderer method programmatically. In this approach, we use the Fragments API to create and configure each fragment instance manually. This allows for greater flexibility, as you can pass data or state directly to the fragment based on runtime conditions.

Here’s an example of how this can be achieved using the Fragments API to dynamically render inspection cards and dynamically react to actions that happen within the fragment:
```
public class InspectionListView extends StandardListView<Inspection> {

    @Autowired
    private Fragments fragments;
    
   // ...
    
   @Supply(to = "allInspectionsVirtualList", subject = "renderer")
    private Renderer<Inspection> allInspectionsVirtualListRenderer() {
        return new ComponentRenderer<>(inspection -> {
            AllInspectionCard card = fragments.create(this, AllInspectionCard.class);
            card.setInspection(inspection);
            card.setAfterAssignmentPerformedHandler(it -> {
                contentTabSheet.setSelectedTab(contentTabSheetMyInspectionsTab);
                getViewData().loadAll();
            });
            return card;
        });
    }
}
```
### Utilizing Fragments for Reusable Components
Fragments are a Jmix mechanism introduced in Jmix 2.3 that allows to define reusable components declaratively using XML. In our example, we used Fragments to create a ```TurbineCard``` component. This component encapsulates all the necessary UI elements and logic to display a turbine’s details in a card layout. By using Fragments, we can define the layout definition of the turbine card in XML in the same way it works for general views.

Here is how we defined a TurbineCard fragment via XML:
```
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<fragment xmlns="http://jmix.io/schema/flowui/fragment">
    <data>
<instance id="turbineDc"
                  class="io.jmix.windturbines.entity.Turbine"/>
    </data>
    <actions>
        <action id="detailsAction"/>
    </actions>
    <content>
        <vbox id="root"
              padding="false"
              spacing="false"
              classNames="white-card cursor-pointer turbine-list-white-card m-m">
            <hbox width="100%" classNames="gap-m p-s">
                <span id="turbineId" dataContainer="turbineDc" property="turbineId" classNames="font-bold"/>
                <hbox justifyContent="END" width="100%">
                    <span id="statusBadge"
                          width="120px"
                          dataContainer="turbineDc"
                          property="status"
                          themeNames="badge pill"
                          classNames="turbine-status"/>
                </hbox>
            </hbox>
            <hbox width="100%" classNames="gap-xl p-s">
                <span dataContainer="turbineDc" property="manufacturer" id="manufacturerName"/>
                <span dataContainer="turbineDc" property="model" id="model"/>
            </hbox>
            <hbox width="100%" classNames="gap-m p-s">
                <hbox alignItems="CENTER" width="100%">
                    <svgIcon resource="/windturbines/icons/location.svg"/>
                    <span id="location"
                          dataContainer="turbineDc"
                          property="location"
                          width="100%"
                          classNames="cut-overflow-text"/>
                </hbox>
                <hbox padding="false" justifyContent="END">
                    <button action="detailsAction" icon="CHEVRON_RIGHT"
                            themeNames="tertiary-inline"/>
                </hbox>
            </hbox>
        </vbox>
    </content>
</fragment>
```
In the Java controller we define how the data is set for the components from the turbine instance.
```
@FragmentDescriptor("turbine-card.xml")
@RendererItemContainer("turbineDc")
public class TurbineCard extends Fragment<VerticalLayout> {

    @Autowired
    private ViewNavigators viewNavigators;
    @ViewComponent
    private Span statusBadge;
    @ViewComponent
    private InstanceContainer<Turbine> turbineDc;

@Subscribe(id = "turbineDc", target = Target.DATA_CONTAINER)
public void onTurbineDcItemChange(final InstanceContainer.ItemChangeEvent<Turbine> event) {
    statusBadge.getElement().getThemeList().add(event.getItem().getStatus().getBadgeThemeName());
}


    @Subscribe
    public void onReady(final ReadyEvent event) {
        getContent().addClickListener(e -> navigateToDetailView(turbineDc.getItem()));
    }

    @Subscribe("detailsAction")
    public void onDetailsAction(final ActionPerformedEvent event) {
        navigateToDetailView(turbineDc.getItem());
    }

private void navigateToDetailView(Turbine turbine) {
    viewNavigators.detailView(UiComponentUtils.getCurrentView(), Turbine.class)
            .withReadOnly(true)
            .editEntity(turbine)
            .navigate();
}
}
```
By leveraging recent improvements form Jmix 2.x we can use Vaadin’s VirtualList and Jmix’s Fragments, we can create mobile-friendly list views that enhance the user experience over a regular data grid. 

### Enhancing Mobile Views with Customized Detail Layouts
One of the key strengths of Jmix is the ability to quickly generate standard CRUD views using Jmix Studio. These views provide a robust foundation that can be easily customized to fit specific application needs. In this section, we will demonstrate how to generate a standard detail view for the Turbine entity and then customize it to enhance usability and appearance.

*Generating Standard CRUD Views*
Using Jmix Studio, you can generate a standard detail view for any entity. This view typically includes fields for each property of the entity, allowing users to view and edit the entity’s data. For the Turbine entity, the generated detail view includes fields for attributes such as turbineId, manufacturer, location, status, and others.

*Using TabSheet for Improved UX*
To improve the user experience, especially on mobile devices, we use a ```TabSheet``` layout to organize the detail view into multiple sections. This approach prevents overcrowding the screen with too many components and reduces the need for excessive scrolling. Each tab can represent a logical grouping of information, making it easier for users to find and interact with the data.
Here is an example of how the TabSheet layout is used in the turbine detail view:
```
<view xmlns="http://jmix.io/schema/flowui/view"
      title="msg://turbineDetailView.title"
      focusComponent="contentTabSheet">
    <!-- ... -->
    <layout spacing="false" padding="false">
        <vbox classNames="layout-header">
            <hbox width="100%" alignItems="CENTER" expand="spacer">
                <button id="backBtn" action="back" classNames="back-button"/>
                <span id="spacer"/>
                <svgIcon resource="icons/notification.svg"/>
            </hbox>
            <h3 id="pageTitle" classNames="page-title"/>
        </vbox>
        <tabSheet id="contentTabSheet" width="100%" themeNames="minimal equal-width-tabs" height="100%"
                  classNames="content-tab-sheet">
            <tab id="detailsTab" label="msg://details">
                <vbox classNames="layout-body" width="100%" height="100%" padding="false" spacing="false">
                    <vbox width="100%" classNames="light-background" padding="false">
                        <scroller width="100%" height="100%">
                            <vbox width="100%" padding="true">
                                <vbox width="100%" classNames="white-card">
                                    <formLayout id="detailsForm" dataContainer="turbineDc">
                                        <responsiveSteps>
                                            <responsiveStep minWidth="0" columns="2"/>
                                        </responsiveSteps>
                                        <textField id="turbineIdField" property="turbineId"/>
                                        <formItem label="msg://io.jmix.windturbines.entity/Turbine.status"
                                                  classNames="status-field-form-item">
                                            <span id="statusField"/>
                                        </formItem>
                                        <textArea id="locationField" property="location" colspan="2"/>
                                    </formLayout>
                                </vbox>
                                <!-- Additional form sections -->
                            </vbox>
                        </scroller>
                    </vbox>
                </vbox>
            </tab>
            <!-- Other tabs -->
        </tabSheet>
    </layout>
</view>
```
*Adjusting visual appearance of Vaadin components through CSS*
The final step in creating a polished detail view is customizing the CSS to ensure that the UI components are visually appealing and consistent with the application’s design language.

With Jmix 2.x and Vaadin 24 the styling of components is now done using standard CSS, which can be applied to the generated views. This is different from the Jmix 1.x / Vaadin 8 based approach with having a Sass as CSS-preprocessor. Recent developments in the world of CSS have made most of the functionality of CSS preprocessors obsolete, like the ability to define CSS variables.

Jmix organizes CSS files under the src/main/frontend/themes/<<theme-name>> directory. You can create separate files for different views or distinct areas of styles. In the case of the Wind Turbines example, we created a directory for shared component styles as well as one directory for view-specific styles.
```
frontend/
└── themes/
    └── jmix-windturbines/
        ├── shared/
        │   ├── background.css
        │   ├── buttons.css
        │   ├── cursor.css
        │   ├── tabsheet.css
        │   ├── text.css
        │   ├── vaadin-lumo-defaults.css
        │   ├── variables.css
        ├── view/
        │   ├── finding-detail-view.css
        │   ├── inspection-list-view.css
        │   ├── login-view.css
        │   ├── main-view.css
        │   ├── tabsheet.css
        │   ├── turbine-detail-view.css
        │   ├── turbines-list-view.css
        ├── jmix-windturbines.css
        ├── styles.css
        └── theme.json
```
In case you want to create new style definitions for new views, you have to add the new file via the @import directive in the main styles.css file.
Let’s look into the example on how we styled the ```<tabSheet />``` component, so that it matches the look & feel of the ```Windturbines``` example:
```
jmix-tabsheet.content-tab-sheet::part(tabs-container) {
    background-color: var(--dark-blue);
    border-radius: 15px;
    padding: 5px;
    margin: 4px 16px 16px;
    height: 36px;
}

jmix-tabsheet.content-tab-sheet vaadin-tab {
    color: var(--lumo-base-color);
}

jmix-tabsheet.content-tab-sheet vaadin-tab[selected] {
    background: linear-gradient(180deg, #EBF2FC 0%, #DBE8FD 100%);
    color: var(--dark-blue);
    border-radius: 10px;
    margin-top: 5px;
    margin-bottom: 5px;
}

jmix-tabsheet.content-tab-sheet::part(content) {
    padding: 0 !important;
}
```
Styling Vaadin components can be slightly different from traditional CSS due to the use of the Shadow DOM. This mechanism encapsulates the component’s styles, preventing them from affecting the rest of the application and vice versa. To style these components, you need to use the ::part pseudo-element.

For detailed information on how to style Vaadin components using the Shadow DOM, you can refer to the <a href="https://docs.jmix.io/jmix/flow-ui/themes/styling-ui-components.html" target="_blank">Jmix Styling UI Components Guide</a>.
Additionally, Vaadin documents all parts & states of their components so that it is easier to style them accordingly: <a href="https://vaadin.com/docs/latest/components/tabs/styling" target="_blank">Vaadin Tabs Styling Documentation</a>.

### Enhancing Mobile Views with Vaadin Utility CSS Classes

Vaadin 24 offers a collection of Utility CSS Classes that help you quickly build responsive and mobile-friendly layouts. These classes can be applied directly in XML views or programmatically in Java code, offering an alternative approach to writing custom CSS. By leveraging these predefined styles, you can save time and reduce complexity while ensuring a consistent, responsive design.

*Applying Utility Classes in XML Views*
One way to utilize Vaadin’s utility classes is by applying them directly in your XML views. This allows you to define layout and style properties without the need for custom CSS. For example, in the “All-Inspections-Card-Fragment,” we are applying classes like bg-base, shadow-s, and p-s to create the card layout for the inspection card:
```
<vbox id="root"
      padding="false"
      spacing="false"
      classNames="m-m bg-base shadow-s p-s rounded-s width-auto">
      <!-- content of the fragment -->
</vbox>
```
These classes handle background color, shadows, padding, and border-radius. The Vaadin documentation contains the utility classes and their corresponding names: ```https://vaadin.com/docs/latest/styling/lumo/utility-classes```.

*Applying Utility Classes Programmatically in Java*

In addition to XML, utility classes can also be applied in Java. In the “My Inspection Card” fragment we set the padding and the gap on the “second row box” via the “addClassNames” method:
```
import com.vaadin.flow.theme.lumo.LumoUtility;

@FragmentDescriptor("my-inspection-card.xml")
public class MyInspectionCard extends Fragment<VerticalLayout> {

    @ViewComponent
    private HorizontalLayout secondRowBox;


    @Subscribe
    public void onReady(final ReadyEvent event) {
        // example on how to add Vaadin Utility class names programmatically
        secondRowBox.addClassNames(
                LumoUtility.Padding.SMALL,
                LumoUtility.Gap.MEDIUM
        );
    }
}
```
In cases where you want to apply styles dynamically, this would only be possible in the Java code. Additionally, using the LumoUtility constants ensures type safety, as these values are predefined and checked by the compiler, reducing the likelihood of errors. Beyond dynamic styling or type safety, this approach is also beneficial if you prefer working in Java. One other advantage of this method is that IntelliJ IDEA / Jmix Studio provide auto-completion and suggestions, making it faster and easier to find the right utility classes directly in your code.

Using Java also allows you to create “abstractions” like shared methods that let you define the applicable styles in one central place. This is not possible in XML, at least without custom CSS classes.

For more details on the available utility classes, refer to the <a href="https://vaadin.com/docs/latest/styling/lumo/utility-classes" target="_blank">Vaadin Utility Classes Documentation</a> as well as the Vaadin blog post about this topic: <a href="https://vaadin.com/blog/building-responsive-layouts-with-vaadin-utility-classes" target="_blank">Vaadin Blog: Building responsive layouts with Vaadin utility classes</a>.

## 4. Summary

This article covers how Vaadin 24 enhances the development of responsive web applications, especially for mobile devices. Vaadin 24 introduces features like FlexLayout and utility classes, which simplify the creation of adaptive layouts that work across various screen sizes.
We then looked at different architectural options for mobile web applications, including unified Jmix applications, dedicated mobile apps with REST backends, and React frontends with Jmix as the backend.

Using the Wind Turbine Project, we explored various topics on how to optimize Jmix applications for mobile devices. This included enabling Progressive Web App (PWA) functionality, enhancing mobile data views by using VirtualList instead of DataGrids, and leveraging Jmix Fragments to create reusable UI components.

Finally, we discussed different approaches to styling: using custom CSS class definition, overriding existing Vaadin component styles, and applying Vaadin’s Utility CSS Classes to create responsive designs and easily style components without the need for custom CSS.

<style type="text/css">
	.mobile-screenshot img {
		max-height: 700px;
		margin: 24px auto !important;
		display: block !important;
	}
</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[FAQ: CUBA Platform - End of the free maintenance period]]></title>
            <link>https://www.jmix.io/blog/cuba-platform-end-of-the-free-maintenance-period</link>
            <guid>https://www.jmix.io/blog/cuba-platform-end-of-the-free-maintenance-period</guid>
            <pubDate>Mon, 28 Oct 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/End_of_the_free_maintenance_period_01_4837a050bd.png">This article answers the most popular questions related to the upcoming end of free support for CUBA Platform.]]></description>
            <content:encoded><![CDATA[**Question**: What does the CUBA Platform end of the free maintenance period mean? 

**Answer**: The end of the free maintenance period for the CUBA Platform means that starting in March 2025, the platform will no longer receive free updates, including bug fixes, security patches, or updates to third-party libraries. Developers using the CUBA Platform will need to migrate their applications to Jmix or adopt a commercial support plan to ensure continued updates and support. 

**Question**: How can I get support for my CUBA Platform project after March 2025? 

**Answer**: After March 2025, support for your CUBA Platform project will follow paid consultancy procedures and rates. If you have questions or need assistance from the Jmix team, they will be addressed under these conditions. CUBA Platform Forum will continue operating, but it will be supported only by the CUBA Platform community members based on their willingness and effort. 

We recommend setting up a private CUBA Platform artifact repository for those requiring ongoing updates—such as bug fixes, security patches, and third-party library updates. The Jmix team will maintain this repository based on paid consultancy upon request. The cost of setting up the private repository will be determined upon inquiry. 

**Question**: Will the CUBA Studio plugin for IntelliJ IDEA receive updates after March 2025?  

**Answer**: No. After March 2025, the Jmix team will not provide any updates to the CUBA Studio, neither related to IntelliJ IDEA updates nor to bug fixes and patches. 

**Question**: How can I migrate my CUBA Platform project to Jmix? 

**Answer**: To migrate your CUBA Platform project to Jmix, follow the <a href="https://docs.jmix.io/jmix/cuba/index.html" target="_blank">migration guide</a>. If you need the Jmix team’s assistance migrating your project, we’re ready to help you with consultancy services. Please get in touch with us to share your project details, and we’ll find a solution that is tailored to your needs. 

**Question**: Can I use an existing CUBA Platform subscription to migrate my project to Jmix? 

**Answer**: If you have an active CUBA Studio subscription, no particular Jmix Studio subscription is needed—it also works for Jmix Studio. However, if you don’t have an active subscription and your project includes premium add-ons like BProc, WebDav, or Maps, you may need a paid Jmix Studio subscription to complete the migration. Please <a href="/contacts/" target="_blank">get in touch with sales</a> if you have questions about the Jmix Studio subscription options. 

**Question**: Does Jmix provide me with everything I’ve used in the CUBA Platform? 

**Answer**: Jmix itself, or in combination with third-party libraries and tools, can provide everything you need to migrate your application. However, there are a few exceptions:
- Email Templates add-on will be available in Jmix in February 2025 
- Tabbed main window mode will be available in Jmix in February 2025 
- GroupTable alternative will be available in Jmix in 2025 
- There are no direct counterparts in Jmix for the following CUBA features, so they should be created on the project level if needed: 
- Folders Panel 
- Entity attribute access control based on entity state 
- IMAP add-on 

**Question**: How long will I get free support if I migrate my project to Jmix?  

**Answer**: If you migrate your project to Jmix, you’ll continue receiving active support and free maintenance according to the <a href="/framework/versioning/" target="_blank">version support policy</a>. Free updates will be provided for projects using the Classic UI (Vaadin 8) until 2028 with the Jmix 1.x branch. This includes bug fixes and specific improvements in the backend and add-ons functionality from Jmix 2.x when porting is possible. You should also take into consideration that if some critical issue is found in an underlying library like Spring, and it is fixed in a version, incompatible with Jmix 1.x (for example in Spring Framework 7), we will not be able to integrate the fix into Jmix 1.x. In this case, we'll investigate the real impact and offer a workaround to mitigate it. Thus, migrating to newer versions of Jmix 2.x, will eventually be required to maintain compatibility with modern libraries and frameworks. For more information, visit the <a href="/blog/extended-support-for-classic-ui/" target="_blank">Jmix Extended Support article</a>. 

**Question**: How long does becoming proficient in Jmix take if I’m a CUBA Platform developer?

**Answer**: For a CUBA Platform developer, it takes a couple of days to become familiar with Jmix 1.x, as it uses Vaadin 8, the same UI technology as CUBA. However, Jmix 2.x requires approximately a month due to its use of Vaadin Flow, a completely new UI framework based on web components built from scratch. To help developers transition faster into Jmix 2.x, we offer a free Udemy course titled <a href="https://www.udemy.com/course/rapid-application-development-with-jmix/" target="_blank">Full Stack Java Web Development | Jmix in Action</a> to support the onboarding process and quickly get you up to speed. You may also <a href="/training/" target="_blank">apply to online Jmix advanced training</a> provided by our team after finishing the Udemy course. 

**Question**: How much effort does it take to migrate from the CUBA Platform to Jmix 2? 

**Answer**: Estimating the effort required to migrate from the CUBA Platform to Jmix 2 is challenging since every project is unique. To help with the initial steps, the Jmix team developed a <a href="https://github.com/jmix-framework/jmix-migration-advisor" target="_blank">migration advisor tool</a> that automatically analyzes your CUBA project and provides a report with rough estimates and recommendations. We suggest starting your migration process with this tool and contacting the Jmix service team afterward for further assistance to ensure a smooth transition tailored to your project needs. 

**Question**: Where can I find resources about the CUBA Platform to Jmix migration? 

**Answer**: Since beginning work on the Jmix project, we have started preparing resources to help developers with migration. You may find helpful the following: 
- <a href="https://docs.jmix.io/jmix/cuba/index.html" target="_blank">Migration guide from CUBA Platform</a> 
- <a href="https://forum.jmix.io/t/jmix-2-x-upgrade-a-practical-guide-for-rent-your-stuff-example/4920/9" target="_blank">Migration guide from Jmix Classic UI by Mario David</a>
- <a href="https://github.com/jmix-framework/jmix-migration-advisor" target="_blank">Migration advisor tool</a>

**Question**: Should I start a new project with the CUBA Platform? 

**Answer**: No. We understand you’re familiar with this great tech, but things change, and we should move forward.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Testing Jmix Application Performance]]></title>
            <link>https://www.jmix.io/blog/testing-jmix-application-performance</link>
            <guid>https://www.jmix.io/blog/testing-jmix-application-performance</guid>
            <pubDate>Mon, 21 Oct 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Cover_Jmix_Bookstore_Performace_e402bb80f1.png">In this article, we’ll dive into that and (hopefully) answer all your performance-related questions.]]></description>
            <content:encoded><![CDATA[## Introduction
One of the questions you might ask when exploring a new technology is how well it performs. In this article, we’ll dive into that and (hopefully) answer all your performance-related questions.

For these tests, we’re using our enterprise demo app, Bookstore, which you can find in this <a href="https://github.com/jmix-framework/jmix-bookstore-2" target="_blank">repository</a>. The goal here is to measure how much of the system's resources a typical Jmix app consumes when handling a large number (relative to Jmix and other stateful applications) of active users' interactions.

## Environment
### Bookstore Adjustments
Before we dive into the results, let’s go over the changes we made to the application to set up performance testing.

**1. Add Actuator and Prometheus Micrometer Registry**
We added these libraries to expose the Prometheus Actuator endpoint at:
```
/actuator/prometheus:
// Monitoring
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
```

You can check out the rest of the endpoint setup and other minor adjustments in <a href="https://github.com/jmix-framework/jmix-bookstore-2/commit/a87d987d9eb458b8b2a6c9c3dc49868a3abb134e" target="_blank">this commit</a>.

**2. Disable Vaadin Checks**
To make the performance tests smoother, we disabled certain Vaadin security checks that aren’t relevant for this testing scenario. Specifically, we turned off XSRF protection and sync ID verification by modifying the application-perf-tests.properties file: 

```
# JMeter tests support
vaadin.disable-xsrf-protection=true
vaadin.syncIdCheck=false
```

**3. Disable Task Notification Timer**

We disabled the Task Notification Timer to simplify the process of recording and emulating HTTP requests in JMeter. This allows us to focus on testing the core application functionality without additional background tasks affecting the results.

**Tooling**
For our performance tests, we used the following additional software:
- <a href="https://www.postgresql.org/" target="_blank">PostgreSQL</a> database.
- <a href="https://github.com/prometheus/node_exporter" target="_blank">Node Exporter</a> to expose server metrics such as CPU loading.
- <a href="https://jmeter.apache.org/" target="_blank">JMeter</a> with <a href="https://github.com/johrstrom/jmeter-prometheus-plugin" target="_blank">Prometheus Listener</a> to generate test load and provide client-side metrics.
- <a href="https://prometheus.io/" target="_blank">Prometheus</a> to collect and store results.
- <a href="https://grafana.com/" target="_blank">Grafana</a> for visualization.
Now that we’ve checked the software configurations, let’s move on to the hardware.

## Server Configuration
Both the application and database servers are virtual machines, each with the following setup:

**Characteristics:**
- **Virtualization:** Proxmox VE, qemu-kvm
- **CPU:** 8 cores, x86-64-v3
- **RAM:** 16 GB
- **HDD:** 200 GB
- **OS:** Ubuntu 22.04

**Host Hardware:**
- **CPU:** Intel Xeon E5 2686 v4 2.3-3.0 GHz
- **RAM:** DDR4 ECC 2400 MHz
- **HDD:** ZFS, Raid1 2-х Sata Enterprise SSD SAMSUNG MZ7L33T8HBLT-00A07

While average, the virtualized setup is capable of handling typical enterprise applications efficiently. For higher loads or more complex systems, further optimization may be needed, but this configuration works well for most internal apps.

## Infrastructure
We’re using three servers in total: two for running tests and one dedicated to collecting metrics:
- **Application Server** contains the Bookstore application, which is run as a boot jar, and a Node Exporter.
- **Database Server** contains a PostgreSQL database and a JMeter application. This server stores persistent data and creates a test load.
- **Metrics Server** includes Prometheus and Grafana applications. Collects and processes metrics.
 ![13.png]({{strapiUrl}}/uploads/13_4e97c68e9c.png)
 
By distributing the workload across dedicated servers for the application, database, and metrics, we ensure efficient resource use and accurate data collection. Let’s move on to the test itself.

## Test
The <a href="https://jmeter.apache.org/usermanual/jmeter_proxy_step_by_step.html" target="_blank">JMeter HTTP(S) Test Script Recorder</a> was used to create the required amount of load without using many resources on web clients. This approach allows a sequence of HTTP requests to be recorded and then replayed in a large number of threads simultaneously using a small amount of resources. However, it is not possible to react to changes in real-time as a full-fledged Vaadin client does. Therefore, a simple testing scenario was used in order to avoid errors and incorrect requests.

<a href="https://github.com/jmix-framework/jmix-bookstore-2/blob/main/performance_testing/jmeter/OrderCreation.jmx" target="_blank">Test plan</a> has been created according to this <a href="https://vaadin.com/blog/performance-testing-a-vaadin-application-part-3-apache-jmeter" target="_blank">instruction</a> with several additions and modifications.

The test plan for each user (thread) represents an infinite loop of the following actions:
1. Load login page
2. Wait an average of loginWait milliseconds
3. Fill credentials (hikari/hikari) and log in
4. Open Order List View
5. Click on "Create" button to open Order Details View with new Order entity
6. Select a customer (one of the first 10 customers in the list, depending on thread number)
7. Create 3 order lines by doing next actions:
   &nbsp;&nbsp;&nbsp;&nbsp; a.	Click on "Create" button in Order Lines block
   &nbsp;&nbsp;&nbsp;&nbsp; b.	Select a product
   &nbsp;&nbsp;&nbsp;&nbsp; c.	Click "OK" button
8.	Confirm order creation by the click on "OK" button
9.	Wait an average of logoutWaitAvg milliseconds
10.	Log out

In order to emulate user actions realistically, there is an average ```clickPeriodAvg``` millisecond waiting time between each user click and the previous request. Login and logout are required for each loop due to the limitations of the HTTP request approach. Logging in is a heavy operation and needs to be balanced with idle time (```loginWait,logoutWait```) to make the test more similar to normal user actions.

Test plan parameters can be specified using ```-J<parameterName>``` command-line arguments during the test run. E.g.:``` -JthreadCound=500```. The next parameters are available:<br/>  
 
| Parameter Name        | Default Value | Description                                              |
|-----------------------|---------------|----------------------------------------------------------|
| host                  | localhost     | Bookstore app host                                       |
| port                  | 8080          | Bookstore app port                                       |
| scheme                | http          | Bookstore app scheme                                     |
| threadCount           | 1000          | The number of users performing the test steps simultaneously. |
| rampUpPeriod          | 60            | How long does it take to "ramp-up" to the full number of users, s. |
| clickPeriodAvg        | 2000          | Average period between clicks, ms.                       |
| clickPeriodDev        | 1000          | Click period min and max deviation, ms.                 |
| loginWait             | 10000         | Time to wait before login, ms.                           |
| logoutWaitAvg         | 30000         | Average period to wait before logout, ms.                |
| logoutWaitDev         | 10000         | Before logout period min and max deviation, ms.         |
<br/>
 
Now that we can emulate the interactions that we’ll track we can check the metrics that will matter based on these interactions.

## Metrics
To assess the performance, we tracked several key metrics throughout the test to provide a view of how the system behaves under load:

- **View loading time** has been measured by HTTP response time for all queries involved in view loading and initialization. JMeter Prometheus listener (see the <a href="https://github.com/jmix-framework/jmix-bookstore-2/blob/main/performance_testing/jmeter/OrderCreation.jmx" target="_blank">test plan</a>) provides these metrics. The following queries are related to the actions:
&nbsp;&nbsp;&nbsp;&nbsp;-	Open List view: LoadOrdersListView-34, OrderCreation-37, OrderCreation-38
&nbsp;&nbsp;&nbsp;&nbsp;-	Open Detail view: CLICK-create-new-order-39, OrderCreation-40, OrderCreation-41
&nbsp;&nbsp;&nbsp;&nbsp;-	Save entity and return to the list view: CLICK-save-order-70, OrderCreation-71, OrderCreation-72
- **Average entity saving time** is measured by Micrometer registry timer in <a href="https://github.com/jmix-framework/jmix-bookstore-2/blob/main/src/main/java/io/jmix/bookstore/view/order/OrderDetailView.java" target="_blank">OrderDetailView.java#saveDelegate</a>
- **CPU usage** metric is provided by Node Exporter on the application server.
- **Average heap usage** metric is provided by Micrometer registry.
- **Allocated heap memory** is set by -Xmx key on application start.
 
These metrics were selected to give us a well-rounded picture of the application’s performance and resource efficiency.

## Running and Measurement
### Environment Setup
First up, we installed Node Exporter on the application server using a tarball, setting the stage for real-time performance monitoring. Meanwhile, on the database server, we deployed PostgreSQL 16.3 via Docker, pulling from the official image to ensure everything runs smoothly.

Next, we brought JMeter 5.6.3 into the mix, also on the database server for load testing magic. Our metrics server was transformed into a powerhouse with Docker as we deployed Prometheus using a tailored configuration. To top it off, we added Grafana 11.1.4 to the metrics server, following the official documentation to for a bit of visualization.

### Building and Running the Application
With our environment in place, it was time to launch the application! We built it with the command ```./gradlew build -Pvaadin.productionMode=true bootJar```, ensuring it was optimized for production. Then we copied the output jar to the application server and launched it using the command:
```java -jar -Dspring.profiles.active=perf-tests -Xmx<N> jmix-bookstore.jar```
where ```<N>``` can be set to 2g, 5g, 10g, or 14g, depending on how much memory we wanted to allocate.

### Test Running
The <a href="https://github.com/jmix-framework/jmix-bookstore-2/blob/main/performance_testing/jmeter/OrderCreation.jmx" target="_blank">test plan</a> is started on the database server using the command below:
```./jmeter -n -t path/to/OrderCreation.jmx  -l logs/log.txt -JthreadCount=1000 -Jhost=<app_server_ip> -JrampUpPeriod=230```

This command runs the JMeter test plan on the database server. It simulates 1,000 users interacting with the application, gradually increasing the load over 230 seconds, and logs the test results in log.txt.

### Measurements
Let's look at the visualization of the results for test with 5GB of heap size and 1000 users working according to the described <a href="https://github.com/jmix-framework/jmix-bookstore-2/blob/main/performance_testing/PERFORMANCE_TESTING.md#implementation" target="_blank">test plan</a> with default parameters and ```rampUpPeriod=230 ``` seconds.

#### Memory
Memory usage can be visualized by metric jvm_memory_used_bytes and looks like:
![memory.png]({{strapiUrl}}/uploads/memory_ca73c4c399.png)
 
#### CPU Usage
CPU usage is measured by node_cpu_seconds metric by summing all modes except "idle":  
![CPU 5G.png]({{strapiUrl}}/uploads/CPU_5_G_4c9560bb4c.png)

As we can see, all 8 cores of the processor are almost fully used (90%). The same distribution is observed for all other tests for 1000 users with default test plan parameters and different allocated memory volumes.

#### View Loading Time
Average view loading time is measured by calculating rate of jmeter_rt_summary_sum metric and summing results for each query involved in particular view loading:
rate(jmeter_rt_summary_sum{label="LoadOrdersListView-34"}[10s]) / rate(jmeter_rt_summary_count{label="LoadOrdersListView-34"}[10s])

and then summing using Grafana expression.
Median value can be obtained by selecting 0.5 quantile of the metric:
sum(jmeter_rt_summary{label=~"LoadOrdersListView-34|OrderCreation-37|OrderCreation-38", quantile="0.5"})

For the Order List View load time looks as follows:  
![Order List View 5g.png]({{strapiUrl}}/uploads/Order_List_View_5g_a4f5804b2c.png)

There is an initial increase in load at the beginning of the test, which later stabilizes after a few minutes. Therefore, we will exclude the first 10 minutes from the analysis and focus on the average resource consumption during one of the subsequent periods when the value remains relatively constant. This typically occurs around the 40-minute mark of the load test.
For OrderListView the average load time is 2.8s (for 1000 users and 5GB of heap size).

#### Entity Saving Time
We can observe the Order Details DataContext saving time using ```jmix_bookstore_order_save_time_seconds``` metric:   
![Save Order 5g.png]({{strapiUrl}}/uploads/Save_Order_5g_d2ade94234.png)

Average entity saving time is relatively small (0.015s) when compared to the view loading time.

## Results
We ran the tests with different heap memory sizes of 2, 5, 10 and 14 GB. In each case, 1000 users worked according to the scenario described above with the following parameters:
- loginWait = 10s
- logoutWaitAvg = 30s
- logoutWaitDev = 10s
- clickPeriodAvg = 2s
- clickPeriodDev = 1s
- rampUpPeriod = 230s
 
The results of measurements are shown in the table below.
| Allocated Heap Memory (GB) | Average Used Heap Memory (GB) (%) | List View Average Load Time (s) | Detail View Average Load Time (s) | Save Order and Return to List View Average Time (s) | Order Saving Average Time (s) | CPU Usage (%) |
|-----------------------------|-----------------------------------|----------------------------------|-----------------------------------|----------------------------------------------------|-------------------------------|----------------|
| 2                           | 1.74 (87%)                        | 7.2                              | 3.6                               | 1.5                                                | 0.300                         | 94             |
| 5                           | 3.4 (68%)                        | 2.8                              | 2.5                               | 1.5                                                | 0.015                         | 90             |
| 10                          | 5.6 (56%)                        | 2.3                              | 2.1                               | 1.3                                                | 0.014                         | 91             |
| 14                          | 6.6 (47%)                        | 2.2                              | 1.9                               | 1.2                                                | 0.017                         | 89             |

## Limitations
Compared to a real usage of the application, the performance tests have the following limitations:
- All users log in with the same credentials.
- All users repeat the same scenario.
- Image loading is disabled to simplify the HTTP requests used in the scenario.
- Task notification timer is disabled for simplicity.

## Putting Results into Perspective
Given the limitations, the application's peak performance aligns with findings from a <a href="https://www.nngroup.com/articles/website-response-times/" target="_blank">Nielsen Norman Group paper</a>, which suggests that response times under 3 seconds are generally acceptable for user satisfaction. In practice, the less time users wait to interact with the system, the better the experience. However, each and every person decides what’s the optimal response time for him based on their performance-related NFRs. 
The results show that increasing heap memory from 2GB to 5GB noticeably boosts performance, cutting load times across views. Beyond 5GB, the gains are minimal. It's important to consider that factors like network latency and server load can add around a second to response times. Therefore, trying to optimize load times below 1.5 to 1.7 seconds may not be worth the extra investment. 
With that said, we don’t recommend using less than 2GB of RAM if you’re building a medium-sized application with 1000 expected users. For most applications with similar configurations, 5GB hits the sweet spot between performance and resource use.

## Conclusion
These tests provide clear insights into how the application scales with different memory configurations. While results may vary depending on your hardware and workload, they highlight optimal setups for smooth performance. Jmix may not be the best choice for applications with massive user traffic like Amazon or Facebook, but it excels as a quick and flexible solution for internal tools or smaller-scale applications like custom CRMs, admin panels, and other business tools.

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Making Web UI in Java Fancy]]></title>
            <link>https://www.jmix.io/blog/making-web-ui-in-java-fancy</link>
            <guid>https://www.jmix.io/blog/making-web-ui-in-java-fancy</guid>
            <pubDate>Mon, 21 Oct 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Making_web_UI_in_Java_fancy_1920x1080_b43a3ad8c1.png">The session teaches how to style your Jmix application and how to create complex views using Jmix.]]></description>
            <content:encoded><![CDATA[The session explains **why Jmix UI is better than Vaadin**. It also explains **why Jmix UI is better than Jmix Classic UI**. The session teaches how to style your Jmix application and how to create complex views using Jmix.

In this workshop, you will learn **the main aspects of Jmix application styling**, such as changing application theme variables, customizing the styling of UI components and where to place your CSS code.

In addition, we will discuss layout specifics and how knowledge of CSS can **help us create better layouts**.

We will put this knowledge **into practice** by improving the layout of the existing view. After that, we will create **a new main view from scratch** to bring a fresh look to our application.

Workshop agenda:

- Advantages of using Jmix over Pure Vaadin
- Jmix Flow UI advantages over Jmix classic UI
- Styling and layout specifics
- Adjusting the application theme
- Creating a complex view with the help of CSS
- Creating a completely custom main view
- Q&A

You can see recording of workshop on our <a href="https://www.youtube.com/live/uBMHp7m64QI?si=S2RiAudiJJlzXlVl" target="_blank">YouTube-channel</a>.

<iframe class="b-youtube-player" width="640" height="360" src="https://www.youtube.com/embed/uBMHp7m64QI?si=S2RiAudiJJlzXlVl" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing Jmix AI Assistant: Your LLM-powered Guide to Rapid Application Development]]></title>
            <link>https://www.jmix.io/blog/jmix-ai-assistant</link>
            <guid>https://www.jmix.io/blog/jmix-ai-assistant</guid>
            <pubDate>Wed, 16 Oct 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_ai_ii_Oia_a_1200a630_2c68a8dae4.png">Meet our super-helpful assistant, answering all your Jmix questions through a natural language chat interface. ]]></description>
            <content:encoded><![CDATA[Jmix has always been to assist developers, empowering them with the tools to ease web development. On our quest to make this process even more approachable, we have created the Jmix AI Assistant which is now available to all users. 

## Overview 

Meet our <a target="_blank" href="https://ai-assistant.jmix.io">super-helpful assistant</a>, answering all your Jmix questions through a natural language chat interface.  

![Jmix_AI_Assistant (1).png]({{strapiUrl}}/uploads/Jmix_AI_Assistant_1_11e83299f9.png) 

With a comprehensive knowledge base put together from the latest <a target="_blank" href="https://docs.jmix.io">documentation</a>, <a target="_blank" href="https://demo.jmix.io/ui-samples/">Flow UI samples</a>, <a target="_blank" href="https://forum.jmix.io/">forum discussions</a>, and training materials, the responses are always relevant to Jmix. The assistant is prepared to help you, whether you seek a general explanation, a code example, or step-by-step guidance. It also maintains context enabling you to clarify certain aspects through follow-up questions. 

## Ask Your First Question 

Follow <a target="_blank" href="https://ai-assistant.jmix.io">this link</a> to ask your first question. All Jmix users get 100 requests per month, and if you need more, feel free to contact us by emailing. 

## Vision 

Our primary goal was for the assistant to help newcomers learn and master Jmix. We also envision it to become a reliable source of insights for those who are well familiar with Jmix, its technology baseline, add-ons, and web development in general. Our ultimate goal is to train it to deliver production-ready solutions to any inquiry, but let's be real — it’s a long road to get there.  

Naturally, future improvements depend on both the assistant’s abilities and the quantity and quality of the materials it uses. Here, you can count on us as we are actively working on it. 

## Feedback and Suggestions 

Your feedback is crucial as we continue to improve this tool to better serve our developer community. Upon receiving an answer, please take a moment to rate your experience and leave a comment. We are also open to your suggestions on scenarios where the AI Assistant could be beneficial. 

We hope you will find the assistant helpful on your journey with Jmix! 
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Join the November Jmix Online Course]]></title>
            <link>https://www.jmix.io/blog/join-the-november-jmix-online-course</link>
            <guid>https://www.jmix.io/blog/join-the-november-jmix-online-course</guid>
            <pubDate>Wed, 25 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/November_Jmix_online_course_1640h856_1_6742d81c85.png">We invite you to the November Jmix online course to learn Jmix in groups with a professional instructor!]]></description>
            <content:encoded><![CDATA[Yahoo! A second online course begins in November - hurry up to get a spot!

The first Jmix Advanced Online Course finished recently, and now we are excited to announce the next group of this course!

We have got a good deal of positive feedback about the previous course from participants:

- The information provided was extremely helpful.
- For the instructor, I will give him a mark of 1000/10.
- I'm very satisfied and highly recommend this course to anyone looking to work with Jmix.

## November's Course Details:

**Dates:** 11 November – 9 December

**Schedule:** Three times a week on Monday, Tuesday, and Thursday

**Exact Dates:**

- November: 11, 12, 14, 18, 19, 21, 25, 26, 28.
- December: 2, 3, 5, 9.

**Format:** Online sessions via Zoom, with ongoing communication in a dedicated Slack channel

**Total Duration:** 39 hours (3 hours per day)

**Time:** 17:00 to 20:00 UTC+2 with little break

**Course Topics:**

- Jmix Application Deployment - 4 hours
- Data Manipulation - 14 hours
- Developing User Interface for Jmix Applications - 14 hours
- Access Control Subsystem - 7 hours

This course is a fantastic opportunity to enhance your skills and gain a solid understanding of Jmix.

If you want to join this group, please, leave your contact information <a href="https://forms.jmix.io/jmix-online-course-november?utm_source=blog&utm_medium=site&utm_campaign=online-course" target="_balnk">here</a>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Transform your Java backend team into full-stack in 14 days. Jmix training for enterprise]]></title>
            <link>https://www.jmix.io/blog/webinar-transform-your-java-backend-team-into-full-stack-in-14-days</link>
            <guid>https://www.jmix.io/blog/webinar-transform-your-java-backend-team-into-full-stack-in-14-days</guid>
            <pubDate>Fri, 20 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Transform_your_Java_backend_team_into_full_stack_1920x1080_1_656f2f01d8.png">We showed you how Jmix training helps your team to progress from Junior Developer to Jmix Senior in a record-fast time.]]></description>
            <content:encoded><![CDATA[We will show you how Jmix training helps your team to progress from Junior Developer to Jmix Senior in a record-fast time. You will see how you can save time studying Jmix documentation and **quickly implement new tools** in your work.

You might ask, "We have documentation, so why should my team attend training?" Our response is that documentation provides knowledge, while **training builds skills**.

It's like reading a book about building a house and being confident that everything will go smoothly just by following the instructions. Even if you have extensive experience in construction, it's easier and faster when an expert points out **precise details**. Not to mention, diving into a new topic is **much more effective with an instructor**. The same goes for Jmix training. You can refer to the documentation, but it won't show you how a mechanism works **through examples**. And it certainly won't quickly answer individual questions online.

Besides, we have a **new training program now**! This year, the training program has been expanded with new materials on the **next generation of Jmix UI using Vaadin Flow technology!** This will be especially interesting for development teams looking to enhance their skills in this super-cool web development technology using Java.

Webinar agenda:

- What are Jmix training and its advantages?
- Why is Jmix training the fastest way to immerse a team in the technology?
- What does every Jmix developer have to know?
- What's new in the Jmix training program 2024?
- What program does your team have to follow step by step to be full-stack Jmix developers?
- Demo training Jmix Security

You can see recording of webinar on our <a href="https://www.youtube.com/live/SApoPynoUug?si=0DJZZ7gd2_bXFd4w" target="_blank">YouTube-channel</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build Cost-Efficient Mobile Business App with Jmix 2.0 and PWA]]></title>
            <link>https://www.jmix.io/blog/build-cost-efficient-mobile-business-apps-with-jmix-20-and-pwas</link>
            <guid>https://www.jmix.io/blog/build-cost-efficient-mobile-business-apps-with-jmix-20-and-pwas</guid>
            <pubDate>Mon, 09 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/PWA_707ed50193.png">Learn how to build mobile-optimized business applications with Jmix. Enhance workflow efficiency and reduce media breaks in business processes with mobile apps.]]></description>
            <content:encoded><![CDATA[While mobile applications for line-of-business (LOB) applications have the potential to significantly enhance internal business operations, their adoption for custom software solutions has been relatively limited, particularly among small and medium-sized businesses. Traditionally, the high investment costs associated with developing dedicated native apps have been a significant barrier, especially when supporting multiple platforms. This has made mobile browser applications a cost-effective alternative. They support the growing need to extend business processes directly to end-users in the field, making mobile solutions increasingly crucial for internal use.

Employees need tools that allow them to access live systems and perform their tasks in real-time. In the past, businesses often needed to use unstructured data entry methods, which then required manual post-processing to integrate with the main business systems. This indirection is negatively impacting operational efficiencies and prone to errors, as they do not allow for real-time interaction with the core systems.

There are numerous use cases for mobile applications in the business application context. These include field service workers, sales teams, and third-party partners who need access to the companies’ systems. Mobile tools can also be vital for customers who require real-time interaction with company services. By providing such tools, companies can ensure that work is done more efficiently and accurately, improving overall productivity and communication.

Previously, Jmix was primarily optimized for desktop use. Although it was possible to create responsive mobile web app UIs using Vaadin / Jmix alone, it was not the common approach because mobile support was not a first-class citizen in Vaadin 8 / Jmix 1.x. Thus, creating mobile solutions normally required developing either a native app or a mobile web app using different technologies, such as JavaScript single-page applications (SPAs). Jmix was mainly used as a backend API in this scenario.

With the release of Jmix 2 and the transition to Vaadin 24, there has been significant improvement in responsive design and mobile application capabilities. Mobile support is now a key feature in Jmix, allowing the same fast delivery and cost-effective development for mobile web apps. This means businesses can now extend their core processes to field users more easily, allowing them to interact with systems directly and perform tasks efficiently.

Now, a single Jmix developer can cope with typical web and mobile applications using a single platform and unified approach to system design. While mobile applications built with Jmix still have technological constraints, significant entry barriers were removed, making it easier for businesses to implement mobile solutions.
In this blog post, you’ll learn how Jmix leverages these technologies, with an example project showcasing the implementation of a mobile application.

## Why Mobile Applications are Important in the Business Context 

Mobile applications significantly enhance business processes by providing real-time access, improved communication, and increased efficiency.

For internal employees, mobile apps are essential for on-the-go access to live systems. Field sales representatives, for example, can use mobile CRM apps to access customer data, log activities, and submit reports while in the field. This real-time access reduces dependency on office-based colleagues and enhances productivity, ensuring that sales activities are logged promptly and accurately. Similarly, warehouse staff, in an inventory management and stock control scenario, can update inventory, scan goods, and perform stock takes in real-time. This reduces delays and errors associated with manual data entry and post-processing, improving overall efficiency and accuracy.

For third-party partners, mobile applications provide crucial system access that would otherwise be unavailable. For example, insurance adjusters handling claims can use mobile apps to access policy details, schedule inspections, log claims, and submit reports on-site. This seamless access ensures efficient operations, reduces downtime, and enhances service quality.

In expense reporting and management, mobile apps allow employees to submit reports and receipts directly from their devices using receipt scans via the camera. Combined with intelligent automated receipt recognition, it reduces administrative tasks and errors, ensures timely reimbursement, and improves financial tracking.

The business environment has evolved significantly. Employees now expect mobile access to data and systems from anywhere, enhancing self-service capabilities and reducing delays in accessing critical information. The rise of remote work has made it standard for employees to access business systems from various locations. Mobile applications support this flexibility, ensuring that work can continue seamlessly regardless of physical location.

It is crucial to leverage technology that allows for efficient development and deployment of line-of-business systems with mobile exposure, without incurring the significant costs associated with dedicated app development. Mobile web apps have emerged as an excellent compromise, offering a cost-effective solution. With advancements in browser capabilities, such as access to Notifications, GPS and other device features, mobile web apps can provide a rich, native-like experience, making them a viable option for businesses looking to enhance their internal processes through mobile technology.

## Progressive Web Apps (PWAs)

To meet the need for effective mobile solutions, one compelling approach is through Mobile Web Apps, specifically leveraging the Progressive Web App (PWA) standard. PWAs offer a cost-effective solution for building mobile applications. Unlike traditional native apps, which require separate development for each platform, PWAs are built using web technologies, namely HTML, CSS, and JavaScript, allowing them to run on any device with a web browser. This significantly reduces development and maintenance costs.

### What are Progressive Web Apps?

Progressive Web Apps are web applications that offer an app-like experience. They combine the efficiency and cost-effectiveness of web applications with the classic advantages of native applications, such as push notifications and the ability to be installed on the user’s home screen. Here are some key characteristics of PWAs:

- **Cross-Platform Compatibility:** PWAs work on any device with a web browser, making them highly versatile.
- **Offline Functionality:** Thanks to service workers, PWAs can function offline or with poor network conditions, ensuring that business processes can continue seamlessly.
- **Push Notifications:** PWAs can send push notifications to keep the communication flow efficient and ensure timely updates on critical business processes.
- **Installation:** Users can install PWAs on their devices directly from the browser, without needing to go through an app store. This is particularly beneficial for internal business apps, as it bypasses the complexities and delays associated with app store approvals.
- **Access to Device Features:** Modern JavaScript APIs allow PWAs to access device functionalities such as GPS, camera, and other sensors, providing a rich, native-like user experience.

Traditionally, native internal business applications required distribution using Mobile Device Management (MDM) solutions, which required all devices to be managed by the company’s MDM system. However, this method is not feasible with the modern Bring-Your-Own-Device (BYOD) approach, where companies do not control their employees’ mobile devices. In a BYOD environment, ensuring secure and seamless app distribution through internal or public app stores is challenging.

This is where Mobile Web Apps, particularly PWAs, shine. They eliminate the need for app stores entirely, allowing employees to access internal applications directly through their browsers. This flexibility is crucial in a BYOD world, where ensuring seamless access without compromising security or usability is paramount. Moreover, PWAs can be updated frequently and seamlessly, adding new features and improvements without requiring users to perform app updates.

### Why Use Mobile Web Apps with Jmix and Vaadin?

While PWAs provide a robust framework for building mobile applications, leveraging them with Jmix and Vaadin brings productivity to the next level for internal business apps. Vaadin, with its advanced capabilities in creating rich web applications, underpins this functionality. Jmix, built on top of Vaadin, enhances the mobile web app development process in several ways:

- **Rapid Development:** Jmix allows for rapid application development, reducing time-to-market for mobile solutions.
- **Integrated Backend:** Jmix provides seamless integration with backend systems, ensuring that mobile apps have access to real-time data and core business processes.
- **Scalability:** Jmix applications are highly scalable, making it easy to expand mobile solutions as business needs grow.
- **Security:** Jmix offers enterprise security features, ensuring that mobile applications are secure and compliant with industry standards.

The significant advantage Jmix brings to the table, empowered by Vaadin, is its focus on development speed and business functionality. Mobile web apps already reduce development costs compared to native apps, but Jmix takes this further by streamlining the development process, whether for desktop or mobile web applications. This efficiency is particularly crucial for line-of-business applications where cost-benefit ratios are an important consideration. Jmix excels in providing out-of-the-box functionality and tools that accelerate development, ensuring that businesses can quickly and cost-effectively develop robust mobile solutions.

## Example Application: Jmix Wind Turbines

We’ve created the Jmix Wind Turbines application to demonstrate how to build a mobile web app in Jmix 2.x that leverages Progressive Web Apps (PWAs) from Vaadin 24. It is optimized for mobile use, showcasing how business processes can be efficiently supported through mobile technology, integrating field workers directly into the system, and enhancing overall workflow.
The business use case for our Jmix Wind Turbines application is the maintenance and inspection of wind turbines. Field technicians use the app to access critical information about the turbines, perform inspections, document findings, and report on maintenance activities.

### Turbine Data Access

The application allows users to access detailed information about each wind turbine, including the model, size, location, and operator contact information. This feature provides technicians with all the necessary background information to prepare for inspections and understand the specific details of the turbines they are working on.

![1-inspection-list]({{strapiUrl}}/uploads/1_inspection_list_9e1884ab66.jpeg)
![2-turbine-list]({{strapiUrl}}/uploads/2_turbine_list_caefa9212a.jpeg)

### Inspection List View

Technicians can view a list of upcoming and past inspections, including dates and assigned personnel. This helps them manage their schedules and ensures that inspections are carried out in a timely manner.

![3-turbine-details]({{strapiUrl}}/uploads/3_turbine_details_6587055cee.jpeg)

### Inspection Documentation

During inspections, technicians document their findings by answering questions about the condition of various turbine components. This includes multiple-choice responses and additional comments. Structured documentation ensures that all aspects of the turbine are checked and recorded systematically.

![4-inspection-detail-1]({{strapiUrl}}/uploads/4_inspection_detail_1_7dc823ecb4.jpeg)

### Findings and Recommendations

Findings can be logged during inspections, detailing any issues or anomalies encountered. Technicians can add detailed descriptions, assign priorities, and attach photos for clarity. They can also create recommendations for addressing these findings. This detailed logging helps in the quick identification and resolution of problems, ensuring that turbines are maintained efficiently.

![5-inspection-detail-2]({{strapiUrl}}/uploads/5_inspection_detail_2_da27fd2b98.jpeg)

### Signature and Finalization

After completing an inspection, the technician can finalize the report by obtaining a digital signature from the operator on a signature canvas. This feature ensures accountability and formalizes the inspection process, providing a verifiable record of the inspection.

![6-inspection-detail-3]({{strapiUrl}}/uploads/6_inspection_detail_3_c59041fd50.jpeg)

This application serves as a practical example of how mobile-optimized business applications can improve efficiency and reduce media breaks in business processes. For instance, handling critical findings in a real-world scenario could involve automatically notifying relevant personnel and scheduling maintenance, ensuring urgent problems are addressed promptly. While the current example application may not include this specific feature, it highlights the potential benefits and efficiencies that can be achieved by integrating mobile technology into field operations.

You can explore this application at <a href="https://demo.jmix.io/windturbines" target="_blank">demo.jmix.io/windturbines.</a>

### Installing as a PWA

To take full advantage of the Jmix Wind Turbines application on your mobile device, you can install it as a Progressive Web App (PWA) directly to your home screen, just like a native app. This allows for quicker access and a more integrated experience. Below is an example of how to add the PWA to your home screen using Chrome on iOS:
1. Open the Application in Chrome: Navigate to the application URL in the Chrome browser on your phone.
2. Access the Share Menu: Tap the share icon at the bottom of the screen, which looks like a square with an upward arrow.
3. Select ‘Add to Home Screen’: Scroll down the options in the share menu and tap on “Add to Home Screen.”
4. Confirm and Install: You can rename the app if you wish, then tap “Add” in the top right corner. The PWA icon will appear on your home screen.

![7-home-screen]({{strapiUrl}}/uploads/7_home_screen_2a280a57f9.jpeg)
![8-full-app-screen]({{strapiUrl}}/uploads/8_full_app_screen_7fd22afe61.jpeg)
![9-login-screen]({{strapiUrl}}/uploads/9_login_screen_336ef4afa2.jpeg)

For more detailed instructions on installing PWAs across different browsers and operating systems, please refer to this guide. This ensures that you can install the PWA regardless of your device or browser preference.

## Conclusion

Mobile applications are crucial for improving internal business operations through real-time access, better communication, streamlined processes, and increased efficiency, especially in modern work environments. For LOB applications or small and medium-sized businesses the high costs of native app development represent a challenge to bring those benefits to the users. Mobile web apps and PWAs try to address this gap by providing a cost-effective solution. Jmix 2 and Vaadin 24 take this to the next level and thus make mobile business applications more accessible and cost-effective.

Progressive Web Apps (PWAs) provide a cost-effective solution for cross-platform mobile application development, offering features like offline functionality, push notifications, and device hardware access, making them ideal for businesses with a BYOD environment.

The Jmix Wind Turbines application is a practical example of how to build mobile-optimized business applications with Jmix, demonstrating how mobile technology can enhance workflow efficiency and reduce media breaks in business processes. The advancements in Jmix 2 and Vaadin 24 empower businesses to develop mobile-optimized applications quickly, extending core business processes to mobile devices for seamless and productive workflows.

<style type="text/css">
	.jmix-website .blog-article__content img {
		display: block;
    	margin: 24px auto;
    	max-width: 30%;
	}
	@media (max-width: 768px) {
    .jmix-website .blog-article__content img {
        margin: 16px auto;
        max-width: 60%;
    }
</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[BPM Time]]></title>
            <link>https://www.jmix.io/blog/bpm-time</link>
            <guid>https://www.jmix.io/blog/bpm-time</guid>
            <pubDate>Sun, 01 Sep 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/photo_2024_09_02_20_11_32_5909e0980b.jpeg">Selecting BPM Solutions: Essential Factors, and how the Jmix Framework simplifies process automation for businesses.]]></description>
            <content:encoded><![CDATA[The concept of BPM (Business Process Management) is far from new. So why are we discussing it again today? Because only recently have the stars aligned. Firstly, the task of process automation has transitioned from being complex and unclear to a "must-have" for businesses. The advantages of process management no longer need justification. Secondly, BPM technologies have become more accessible and mature.

As a result, we see that the BPM market is steadily and confidently growing. For instance, Precedence Research estimates a growth rate of 14.5% through 2033. This may not be hype, but that's for the better—it allows time to thoughtfully consider what type of BPM you really need.

![bpm_jmix_0d88117429.jpg]({{strapiUrl}}/uploads/bpm_jmix_0d88117429_28b636292c.jpg)

## Choosing BPM Solutions: Key Criteria

The most obvious criterion is cost. Businesses no longer want to pay millions of dollars per year for software licenses that solve relatively mundane tasks. BPM is no longer rocket science. Companies need a reliable and straightforward tool at a reasonable price.

The second requirement—no exotic solutions! No one needs a brilliant development with a unique methodology or process modeling notation. What is needed is just another brick in your IT architecture that can perform its function in a completely standard way.

That’s probably enough—the solution should be economical and technologically sound. This is why we're currently witnessing a wave of interest in open-source BPM engines. They have matured enough to fit into corporate landscapes, and previous concerns about code quality, reliability, and performance are no longer relevant. Moreover, the BPMN notation they use has become the de facto standard in process modeling.

In theory, this sounds appealing, but what about in practice? Naturally, a bare engine won't solve the problem. You'll need to invest significant effort into setting up the development of automated processes. While you might save on expensive software, team expenses will remain, and the BPM learning curve is steep—it may take a long time before developers produce their first process, often several months.

However, there’s a way to save time and money: to enable your team to start working efficiently sooner, you can use a ready-made set of development tools like the Jmix Framework, which includes a BPM component based on the Flowable engine. You'll still need to learn, but this will take significantly less time—around one month. And if you’re already familiar with the Jmix platform itself, it will be even faster.

The time for BPM has come—business demands for process automation will only continue to grow. Therefore, it’s best to prepare the right tools and a skilled team to meet these challenges now.

Jmix is an open-source platform for rapid development of business applications on Java.

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix Services: for all business occasions]]></title>
            <link>https://www.jmix.io/blog/jmix-services-for-all-business-occasions</link>
            <guid>https://www.jmix.io/blog/jmix-services-for-all-business-occasions</guid>
            <pubDate>Fri, 30 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Servisnye_uslugi_v_Jmix_1200h630_73f9c4aa48.png"> Jmix - more than just a platform. Also, services for boosting your projects. In this article we’ll cover how Jmix services help teams create business applications in a record short time and find solutions to any situation.]]></description>
            <content:encoded><![CDATA[We can confidently say Jmix can be beneficial to you not only as a development tool. This is confirmed by the successful stories of using Jmix services of our customers like developers, corporations, digital agencies. 

We want to introduce you to our services that enable earning Jmix and promptly resolving issues during development. Jmix is not just a development platform but also provides accompanying services to enhance the productivity of development teams and facilitate the rapid creation of business applications. 
 
<div class="highlighted-text">
<p>
Services are types of support that address the primary needs of businesses and developers throughout the software creation and implementation process. 
</p>
</div>

<h2 class="purple"><a href="/services-support/">COMMERCIAL SUPPORT</a></h2>

Comprehensive and expert support at all stages of development: from project start to deployment. We don’t just explain documentation upon your request. We dive into the situation, write code and offer detailed ready-made solutions. Besides, we explain how to work with it further. We help avoid situations where errors snowball, their correction consumes precious employee time and development stalls. 

<h2 class="red">OUTSTAFFING</h2>

A 3-in-1 service to boost your project: task execution, training your employees during the process, and getting the Jmix team’s expertise. You can hire our core Jmix developers full-time for complete project immersion and rapid development. 

When might you need the outstaffing service? At any stage of the project. 

At the beginning: a quick start to work while the rest of the team immerses themselves in the technology. 

In the middle: advancing and organizing processes, creating universal methods to speed up work. 

At the end: strengthening the team to meet project deadlines. 

<h2 class="green"><a href="/training/">CORPORATE TRAINING</a></h2> 

Training helps not to waste time on studying documentation. The practical assignments for consolidating and practicing the material allow you to quickly apply the acquired knowledge in practice. 

Training is suitable not only for new employees or when you are starting work with the platform. Send your team to individual training on Jmix functionalities and implement new technologies in your projects. Training is conducted on a convenient schedule for groups of up to 12 people and only on topics you need. 

<h2 class="yellow"><a href="https://forms.jmix.io/jmix-online-course">ONLINE COURSES</a></h2>

A new format of online training by Jmix experts for all interested developers. This is an ideal option for individual developers and small groups. The schedule and the program are formed when participants enroll in specific topics. If you are interested in taking part in the online course submit the requests <a href="https://forms.jmix.io/jmix-online-course">here</a>. 

<h2>OUR GOAL IS YOUR SUCCESS</h2>

Jmix Services are like an umbrella in autumn. They might come in handy at any moment. With them, the situation becomes more controllable, and you always have a plan B. 

You won’t be left alone with a problem. We’ll help you find a way out and meet your deadlines. 

Email us by info@jmix.io to tell us what situation you need expert help with, and we will definitely find an effective solution. 
  
<div class="cta-block">
	Please <a href="/services-support/">contact us</a> to find the most effective solution of your situation.
</div>

<style type="text/css">
	.highlighted-text {
		border: 1px solid #aeaad6;
		padding: 20px 0 20px;
		margin: 20px 0 30px;
		text-align: center;
	    border-radius: 10px;
	    background: #fafaff;
	    color: #11151b;
	    font-weight: 500;
	    box-shadow: 0px 38.52px 25.48px 0px #342A980B;
	}
	.cta-block {
		margin: 25px 0 30px 0;
		-webkit-box-pack: center;
	    -ms-flex-pack: center;
	    -webkit-box-align: center;
	    -ms-flex-align: center;
	    align-items: center;
	    background: #e8e2ff;
	    border: 1px solid #342a98;
	    border-radius: 10px;
	    display: -webkit-box;
	    display: -ms-flexbox;
	    display: flex;
	    justify-content: center;
	    min-height: 88px;
	}
	.cta-block a {
		font-weight: 700;
		text-decoration: underline;
	}
	.green, .green a {
		    color: #41b883!important;
	}
	.red, .red a {
		color: #fc1264!important;
	}
	.purple, .purple a {
		color: #342a98!important;
	}
        .yellow, .yellow a {
                color: #fdb42b!important;
        }
</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: Mastering Full-stack Java Development: Frameworks and insights for 2024]]></title>
            <link>https://www.jmix.io/blog/full-stack-java-development</link>
            <guid>https://www.jmix.io/blog/full-stack-java-development</guid>
            <pubDate>Thu, 01 Aug 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/full_stack_java_e8e9971e9f.jpg">In this tech talk we discuss leveraging full-stack Java development as one of the available solutions in the market.]]></description>
            <content:encoded><![CDATA[Choosing the right technology stack for your next enterprise application project can be mindblowing.
In this tech talk we’ve invited Anees Ur-Rehman, a seasoned professional with over two decades of experience in enterprise development, to uncover these common challenges and share his expertise on leveraging full-stack Java development as one of the available solutions in the market.
You can see recording of webinar on <a target="_blank" href="https://youtube.com/live/FxkDE-Vo51g">our youtube channel</a>.

<youtube data-video-id="FxkDE-Vo51g"></youtube>

<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: Development business software without boilerplate and overengineering]]></title>
            <link>https://www.jmix.io/blog/development-business-software-with-java</link>
            <guid>https://www.jmix.io/blog/development-business-software-with-java</guid>
            <pubDate>Sat, 27 Jul 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/dev_business_software_with_java_07449d8acd.jpg">In this webinar, we discuss how to maximize development productivity in custom enterprise software development with Java.]]></description>
            <content:encoded><![CDATA[In this webinar, we discuss how to maximize development productivity in custom enterprise software development with Java. The webinar is focused on tech leaders who are new to Jmix and meet the challenges with high expenses for maintaining the existing technology stack. 

 You can see recording of webinar on <a target="_blank" href="https://youtube.com/live/BddNow6bYpk">our youtube channel</a>.

<youtube data-video-id="BddNow6bYpk"></youtube>


<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: How can partners make money using Jmix services?]]></title>
            <link>https://www.jmix.io/blog/partners-jmix</link>
            <guid>https://www.jmix.io/blog/partners-jmix</guid>
            <pubDate>Thu, 25 Jul 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/how_partners_jmix_make_money_9d316b9f10.jpg">Learn how to grow software development business with Jmix services improving efficiency and getting extra income.]]></description>
            <content:encoded><![CDATA[Jmix is more than just a development tool, it's a complete ecosystem that enhances developers' productivity and accelerates business application creation. In this session, we introduce you to our services, including learning Jmix, training others, resolving development issues quickly, and validating your expertise through developer certification.
This webinar is particularly valuable for partners and customers looking to maximize development efficiency, scale their teams, or find new ways to monetize their knowledge.

Webinar agenda:
- Jmix services and their advantages
- Customer Stories Jmix Services vs Traditional Outsourcing
- Use cases of Jmix services for monetizing your expertise


 You can see recording of webinar on <a target="_blank" href="https://youtu.be/ujZt2UCVRJ8">our youtube channel</a>.

<youtube data-video-id="ujZt2UCVRJ8"></youtube>


<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: What's new in Jmix]]></title>
            <link>https://www.jmix.io/blog/whats-new-in-jmix-2-3</link>
            <guid>https://www.jmix.io/blog/whats-new-in-jmix-2-3</guid>
            <pubDate>Wed, 17 Jul 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/whats_new_in_jmix_23_b4326c16f3.jpg">Discover the latest features and improvements in our newest release. ]]></description>
            <content:encoded><![CDATA[Discover the latest features and improvements in our newest release. Jmix 2.3 key updates:
 
- New Apache Superset integration add-on
- UI fragments
- UI improvements: lazy tabs, TwinColumn component 
- Data repositories in views
- Authorization Server improvements
- Liquibase changelog aggregation
 You can see recording of webinar on <a target="_blank" href="https://youtu.be/i9-CV8CZ2IY">our youtube channel</a>.

<youtube data-video-id="i9-CV8CZ2IY"></youtube>



<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Join the Jmix online course!]]></title>
            <link>https://www.jmix.io/blog/join-the-jmix-online-course</link>
            <guid>https://www.jmix.io/blog/join-the-jmix-online-course</guid>
            <pubDate>Tue, 09 Jul 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Online_course_eng_announcement_1640h856_28457ed443.png">We invite you to the Jmix online course to learn Jmix in groups with a professional instructor!]]></description>
            <content:encoded><![CDATA[We are glad to announce the enrollment of the groups of the Jmiх courses. They are perfect for individual developers and independent small groups. Our course will fast-track your learning Jmix and improve in the different areas.

The online course will include the most popular topics and follow an everyday schedule.

Choose topics you are interested in from the list <a target="_blank" href="https://forms.jmix.io/jmix-online-course?utm_source=blog&utm_medium=site&utm_campaign=services">here</a>, send us a request, and we will contact you with precise details and courses’ cost.

Expand and enhance your skills with Jmix expert-led online courses!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 2.3 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-2-3-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-2-3-is-released</guid>
            <pubDate>Fri, 28 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/JMIX_2_3_004a13e602.png">Overview of the new features and important changes of the Jmix 2.3 feature release.]]></description>
            <content:encoded><![CDATA[Jmix 2.3 has recently been released. In this article, we will explore the new features and improvements that have been introduced in this update.

For more information and guidance on migration, please visit the <a href="https://docs.jmix.io/jmix/2.3/whats-new/index.html" target="_blank">What's New</a> page in the documentation.

## Superset Add-on

<a href="https://superset.apache.org" target="_blank">Apache Superset</a> is a leading open-source data exploration and visualization solution. It allows you to create highly customizable dashboards that contain various charts. The charts are populated from datasets which obtain data from your database using SQL queries.

The Jmix Superset add-on lets you easily connect your application to the Apache Superset server and embed dashboards to Jmix views. For example, the main view of the Bookstore application can contain a dashboard with the aggregated information about customer orders:

![superset-1.png]({{strapiUrl}}/uploads/superset_1_6dd810c66e.png)

You only need to specify the URL and user credentials to connect to the Superset server, and the add-on will take care of requesting, refreshing and using security tokens when displaying  embedded dashboards.

After creating a dashboard in Superset, you should prepare it for embedding. The Superset generates an ID to refer to this dashboard from outside.

The `dashboard` UI component provided by the add-on allows you to include a dashboard in an application view. You only need to specify the dashboard ID in the `embeddedId` attribute:

```xml
<superset:dashboard id="ordersDashboard" 
		embeddedId="4bc14bf5-a3ec-4151-979e-a920420e1f66"  
        height="100%" width="100%" maxWidth="50em"/>
```

The Superset server connects directly to the application database. In order to filter data on dashboards according to user permissions or by any other criteria, you can pass a list of constraints from the view to the dashboard. In the following example, the dashboard will show data for the current tenant only:

```java
@Install(to = "ordersDashboard", subject = "datasetConstraintsProvider")  
private List<DatasetConstraint> ordersDashboardDatasetConstraintsProvider() {  
    DatasetConstraint constraint = new DatasetConstraint(25,  
            "tenant = '" + tenantProvider.getCurrentUserTenantId() + "'");  
    return List.of(constraint);  
}
```

For detailed information on how to use the Superset add-on with your Jmix application, please refer to the <a href="https://docs.jmix.io/jmix/2.3/superset/index.html" target="_blank">Superset add-on documentation</a>.

## Support for OpenSearch

You can now use the Jmix Search add-on with the <a href="https://opensearch.org/" target="_blank">OpenSearch</a> service.  All features of the add-on (declarative index definitions, indexing queue, UI search field, etc.) work identically with both OpenSearch and Elasticsearch engines. Choosing between OpenSearch and Elasticsearch boils down to specifying the appropriate starter dependency in `build.gradle`. When the add-on is installed from Marketplace, OpenSearch is selected by default.

## Fragments

A fragment is a new UI building block designed for code reuse and decomposition of complex UI structures. In terms of their features, fragments lie between views and composite components. 

The same as a view, a fragment can have an XML descriptor with data components and actions. It supports component injection and event handlers in the fragment class. Studio offers a template for creating an empty fragment and the same UI designer as for views.

On the other hand, a fragment can be used as a component of views and other fragments.

The purpose of fragments is to provide you with more flexibility in structuring and reusing UI code that is bound to the data model.

The example below can give you an idea of how to create and use a fragment. This simple fragment represents data of an embeddable entity called `Money`.  The UI designer with the fragment's XML and preview looks like this:

![fragment-1.png]({{strapiUrl}}/uploads/fragment_1_75c9fa5bf0.png)

The fragment's class (AKA controller) can define setters to accept parameters from the host. In our case, it receives a `Money` instance and sets it to its own data container:
```java
@FragmentDescriptor("money-fragment.xml")  
public class MoneyFragment extends Fragment<JmixFormLayout> {  
  
    @ViewComponent  
    private InstanceContainer<Money> moneyDc;  
  
    public void setMoney(Money money) {  
        moneyDc.setItem(money);  
    }  
}
```

To include the fragment in a view, we use the `fragment` element and specify the fragment class. Our host view contains two instances of the same fragment:
```xml
<vbox>  
    <h4 text="msg://price"/>  
    <fragment id="unitPriceFragment" 
		    class="io.jmix.bookstore.view.moneyfragment.MoneyFragment"/>  
</vbox>  
<vbox>  
    <h4 text="msg://discount"/>  
    <fragment id="discountFragment" 
		    class="io.jmix.bookstore.view.moneyfragment.MoneyFragment"/>  
</vbox>
```

The host view controller invokes the fragment's API methods to pass the `Money` instances:
```java
@ViewComponent  
private MoneyFragment unitPriceFragment;  
@ViewComponent  
private MoneyFragment discountFragment;

@Subscribe  
public void onReady(final ReadyEvent event) {  
    unitPriceFragment.setMoney(orderLineDc.getItem().getUnitPrice());  
    discountFragment.setMoney(orderLineDc.getItem().getDiscount());  
}
```

## Data Repositories

This release completes the implementation of support for Spring Data repositories as first class citizens in the Jmix ecosystem. Now you can easily use them in views for loading and saving data, while keeping compatibility with all standard Jmix UI features like filtering, pagination and sorting.

When creating a view using the wizard, you can notice the *Use Data Repository* checkbox in the *Advanced* section. If you turn it on, you will be able to select an existing data repository. The wizard will generate a view with load and save delegates invoking methods of your repository.

The list load delegate will extract the Spring Data `PageRequest` from the Jmix `LoadContext` object and provide filtering conditions and other options to the data repository in the `JmixDataRepositoryContext` object.  You can modify the delegate logic, for example to provide an initial sorting:

```java
@Install(to = "customersDl", target = Target.DATA_LOADER)  
private List<Customer> loadDelegate(LoadContext<Customer> context) {  
    // convert Jmix paging and sorting parameters to Spring Data PageRequest  
    PageRequest pageable = JmixDataRepositoryUtils.buildPageRequest(context);  
    if (pageable.getSort().isEmpty()) {  
        // set initial sorting  
        pageable = pageable.withSort(Direction.ASC, "firstName", "lastName");  
    }  
    // provide Jmix conditions, fetch plan and hints  
    JmixDataRepositoryContext jmixContext = JmixDataRepositoryUtils.buildRepositoryContext(context);  
    // invoke repository method and return the page content  
    return repository.findAll(pageable, jmixContext).getContent();  
}
```

The above code does the same as the following JPQL in the loader:
```xml
<loader id="customersDl" readOnly="true">  
    <query>  
        <![CDATA[select e from bookstore_Customer e  
        order by e.firstName asc, e.lastName asc]]]]><![CDATA[>  
    </query>  
</loader>
```

All methods of repositories that extend `JmixDataRepository` now support `JmixDataRepositoryContext` as an additional parameter. This makes the data repositories compatible with the `genericFilter` and `propertyFilter` components and declarative data loaders.

## Lazy TabSheet Tabs

The TabSheet component is usually used when there are many UI controls on a view and you want to group them into different tabs.

In this release we added the ability to mark a tab as `lazy`. The content of such a tab will not be loaded automatically when the view is opened. If you use this feature for tabs that contain a lot of components and require loading of additional data, it can significantly improve performance.

The loading of data and other initialization for lazy tabs should be done in the tabsheet's `SelectedChangeEvent` listener, for example:

```java
@ViewComponent  
private CollectionLoader<Position> positionsDl;  
  
private boolean positionsInitialized;

@Subscribe("tabSheet")  
public void onTabSheetSelectedChange(final JmixTabSheet.SelectedChangeEvent event) {  
    if ("positionTab".equals(event.getSelectedTab().getId().orElse(null))  
            && !positionsInitialized) {  
        positionsDl.load();  
        positionsInitialized = true;  
    }  
}
```

Keep in mind also that components located on a lazy tab cannot be injected into the view class, because they don't exist at that moment. So you have to use the `UiComponentUtils.getComponent()` method to get them after the tab has been initialized.

## TwinColumn Component

The new `twinColumn` component is a great addition to the Jmix UI component library. It provides users with a familiar and convenient way to select items from a list:

<img src="{{strapiUrl}}/uploads/twincolumn_1_a55e9ea2b3.png" width="500">

## Authorization Server Add-on

We've extracted the Authorization Server module into a separate add-on with its own <a href="https://docs.jmix.io/jmix/2.3/authorization-server/index.html" target="_blank">documentation</a> and installation process. Previously it was installed together with the Generic REST add-on. So now when installing the Generic REST add-on, you should decide how you will protect its endpoints: by using the Authorization Server or OIDC add-ons, or by some other means.

The new feature of the Authorization Server add-on is the implementation of Resource Owner Password Credentials grant. This grant type is not recommended by OAuth specification, but we received a lot of requests from the application developers and decided to implement it. It can be used in trusted, legacy, or highly controlled environments for simple authentication of REST clients as registered Jmix application users.

## Liquibase Changelog Aggregation

The most prominent new feature in Studio is the ability to aggregate existing Liquibase changelogs. It allows developers to combine several latest changelogs into one and get rid of duplicated actions in changesets.

Consider the following situation: due to iterative development of the data model you have three changelogs. The first one adds the `ALPHA` column, the second adds the `BETA` column, and the third adds `GAMMA` and removes `ALPHA`.  So the changes introduced in the first changelog are overridden by the third one.

The **Aggregate Liquibase Changelogs** action is available in the data store context menu. It allows you to select any number of latest changelogs for aggregation. Let's select the three changelogs described above:

![aggregate-changelogs-1.png]({{strapiUrl}}/uploads/aggregate_changelogs_1_abbcbb69d0.png)

The resulting changelog will include only changes that really bring the database schema in sync with the data model: adding `BETA` and `GAMMA` columns:

![aggregate-changelogs-2.png]({{strapiUrl}}/uploads/aggregate_changelogs_2_6e954a2f8a.png)

Studio will remove the selected changelog files and add the new aggregated one. To keep the set of changelogs compatible with databases where old changelogs have already been executed, Studio can add a precondition to the new changesets. This precondition instructs Liquibase not to execute the new changesets if the first changlog from the replaced list have been executed:
```xml
<preConditions onFail="MARK_RAN">  
    <not>  
        <changeSetExecuted id="1" author="bookstore"  
			changeLogFile="io/jmix/bookstore/liquibase/changelog/2024/06/27-1-add-alpha.xml"/>  
    </not>  
</preConditions>
```

The changelog aggregation should be performed with caution, because it actually doesn't analyze and reproduce the content of the existing changelogs. Instead, it generates a new changelog for the difference between the schema before the first selected changelog and the current model. So if the aggregated changelogs contain some data updates or schema changes that are not reflected in the model (for example, stored procedures), they will be lost.

Obviously, the most natural and safe way to use this functionality is to aggregate changelogs before committing latest changes to a shared source code repository, or merging a feature into a common branch.

## Other Studio Improvements

This release introduces several Studio features that improve the developer experience.

- The Jmix tool window has an action to generate a UI exception handler.
- The **Convert to** action in the Jmix UI structure context menu allows you to convert one component into another with a single click. The **Wrap into** action can wrap multiple selected components into a TabSheet tab.
- Improved JPQL Designer layout.
- Improved Dockerfile generation.

See the list of all Studio improvements in our <a href="https://youtrack.jmix.io/issues/JST?q=Fixed%20in%20builds:%202.3.0,-2.2.*%20type:%20Feature,Improvement,Usability" target="_blank">issue tracker</a>.

## What's next?

Our plans for the next feature release in October 2024 include several very important features in Jmix UI:

- Integration of a few third-party JavaScript components: Calendar, PivotTable and Kanban board.
- Possibility to use fragments to define inner layout of VirtualList items.
- Tabbed main window mode, when views are opened in the tabs inside the main window instead of the browser tabs.

The latter feature is the most requested by developers who want to migrate their solutions from the Classic UI. So we are going to provide a solution for working with multiple views in a single browser tab, while sacrificing some browser capabilities such as history and deep links.

Another planned feature that can help with migration from older versions of the platform is the declarative UI permissions. This feature was present in CUBA Platform and allowed application developers and administrators to restrict access to arbitrary parts of the UI (fields, buttons, actions) without having to write any code.

On the Studio side, we are going to improve the Jmix UI inspector usability and provide more editors for UI component properties (for example for `formLayout.responsiveSteps`). Also, we will present the first results of our work on integrating with external data sources.

Like always, we will allocate considerable time for bug fixing, small feature additions, and performance enhancements.

Our detailed roadmap for future releases is available as a <a href="https://github.com/orgs/jmix-framework/projects/23/views/1" target="_blank">GitHub project</a>. Patches for the current version 2.3 will be released approximately once a month to ensure regular updates.

We appreciate your feedback on our <a href="https://forum.jmix.io" target="_blank">forum</a>, and we are thankful to all those who have submitted pull requests and shared their ideas, suggestions, and bug reports!
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 2 Bookstore Demo Overview]]></title>
            <link>https://www.jmix.io/blog/jmix-bookstore-overview</link>
            <guid>https://www.jmix.io/blog/jmix-bookstore-overview</guid>
            <pubDate>Sun, 23 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/jmix_bookstore_bebfa726f6.png">Discover Jmix's capabilities through a real-world B2B web-application modeled after the well-known Nordwind Bookstore, showcasing such functionalities and add-ons as custom filtering, BPM, Maps, and more.]]></description>
            <content:encoded><![CDATA[Jmix Bookstore is a comprehensive example application built with Jmix - a full-stack platform for business applications. It showcases the operations of a retail business that specializes in shipping books across the US.
 
Discover Jmix's capabilities through a real-world B2B web-application modeled after the well-known Nordwind Bookstore, showcasing such functionalities and add-ons as custom filtering, BPM, Maps, and more. Whether you're a developer looking for inspiration or someone curious about what Jmix can do, this video is for you. 

You can see this tutorial on <a target="_blank" href="https://youtu.be/xQIlKIdPYDg">our youtube channel</a>.
Find project source code <a target="_blank" href="https://github.com/jmix-framework/jmix-bookstore-2">on GitHub</a>.
Try Jmix Bookstore Demo <a target="_blank" href="https://demo.jmix.io/bookstore">Online</a>.

<youtube data-video-id="xQIlKIdPYDg"></youtube>

<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Tutorial: Report Generation in Java Web Applications]]></title>
            <link>https://www.jmix.io/blog/report-generation-in-java-web-applications</link>
            <guid>https://www.jmix.io/blog/report-generation-in-java-web-applications</guid>
            <pubDate>Tue, 18 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/maxresdefault_1_47b9941a3b.jpg">In this guide we’ll cover how to create reports, how to customize and format your reports’ appearance as admins using DOCX or XLSX templates and a few options on how you can allow end users to generate printable forms.


]]></description>
            <content:encoded><![CDATA[Discover how to use an out-of-the-box reports solution for your Java web application using Jmix Reports.
In this guide we’ll cover how to create reports, how to customize and format your reports’ appearance as admins using DOCX or XLSX templates and a few options on how you can allow end users to generate printable forms.

You can see this tutorial on <a target="_blank" href="https://youtu.be/nVYKk63O34M">our youtube channel</a>.
Project repository on <a target="_blank" href="https://github.com/jmix-framework/jmix-onboarding-2">GitHub</a>.

<youtube data-video-id="nVYKk63O34M"></youtube>

## Timestamps:

+ <time-code data-time="0:00"> General information
+ <time-code data-time="0:55"> Data Model
+ <time-code data-time="1:50"> Install Add-on
+ <time-code data-time="2:24"> Simple Report
+ <time-code data-time="5:34"> Value Formats
+ <time-code data-time="5:58"> Template Formatting
+ <time-code data-time="7:34"> Master-Detail Report
+ <time-code data-time="8:57"> User Card Report
+ <time-code data-time="10:04"> Report Generation Button
+ <time-code data-time="5:58"> Template Formatting
+ <time-code data-time="12:20"> IFrame Integration

<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[5 Best Java Frameworks for Web Development in 2024 ]]></title>
            <link>https://www.jmix.io/blog/5-best-java-frameworks-for-web-development-in-2024</link>
            <guid>https://www.jmix.io/blog/5-best-java-frameworks-for-web-development-in-2024</guid>
            <pubDate>Tue, 14 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/5_Best_Java_Frameworks_1200e630_faf617d7cd.png">Discover the top 5 Java frameworks for web development in 2024. Explore the latest tools and technologies to enhance your Java web development projects.]]></description>
            <content:encoded><![CDATA[## Introduction 

CRUD applications form the backbone of many software projects, making Java frameworks crucial for efficient web development today. If you're searching for the best Java frameworks for web development in 2024, chances are you’re looking for a quick way to generate web UIs on top of your database for typical data interactions: Create, Read, Update, and Delete. And most importantly – with minimal learning required. Unfortunately, the growing complexity of web technologies often complicates what should be straightforward, raising barriers to resolving simple tasks like creating CRUD applications with minimum effort. 

Traditionally, web applications are split into two parts: front-end focusing on the UI and back-end working on the server-side logic. Sounds efficient, right? But here's the twist – this split often means doubling up the team size, but not necessarily doubling the output. The increased communication overhead between these divided teams can slow down the process, negating the expected 'speed' brought about by specialization. This was all fine during times of generous VC funding. 

In today's tech landscape, there's a noticeable shift towards frameworks that bring everything under one roof. This shift is especially challenging if your team is backend-heavy and you need to deliver projects within budget. 

## Modern state of Java fullstack web applications 

In the realm of Java full-stack web application frameworks, each offers unique advantages suitable for various scenarios. The popularity of a framework can be evaluated from different angles, including its appeal in the market and the quality of the developer experience it provides. 

Ease of use and overall developer experience paired with well-rounded documentation have always been an important aspect that attracts new developers and influence companies looking to switch to another framework. This article emphasizes the developer's experience rather than performance metrics. 

Although Java frameworks universally promote code reusability and reduce boilerplate—enhancing developer productivity and minimizing bug risks—the degree to which they prioritize the developer's experience varies. 

According to a JetBrains <a target="_blank" href="https://www.jetbrains.com/lp/devecosystem-2023/java/">survey</a> of over ten thousand Java developers, several frameworks stand out. Notably, Spring Framework has emerged as the leading choice for modern web development, surpassing JSF, which had long been prevalent in the enterprise sector. We'll explore a selection of frameworks, focusing on the most relevant ones in today's trends, to briefly discuss their features along and highlight their pros and cons. 

## Spring MVC + Thymeleaf

![thymeleaf.png]({{strapiUrl}}/uploads/thymeleaf_a96db3828e.png)

<a href="https://docs.spring.io/spring-framework/reference/web/webmvc.html">Spring MVC</a> is often paired with <a target="_blank" href="https://www.thymeleaf.org/">Thymeleaf</a>, a server-side Java templating engine for web and standalone environments.  

Thymeleaf helps separate the back-end logic and front-end presentation. It uses HTML-like syntax with embedded expressions for its templates. This means you can use plain HTML files for your templates, which can be viewed and edited in browsers as static files. 
 
Thymeleaf also provides an expression language for conditional statements, loops, and data manipulation. It integrates with various Java libraries and extends its functionality through different dialects and template modes, such as XML, JavaScript, and CSS. 

With a vibrant community, Thymeleaf provides a developer-friendly environment, supported by comprehensive documentation. Thymeleaf supports static site generation, enabling deployment on platforms like Netlify or Vercel for better performance and security. It has strong and consistent support, particularly in the Spring ecosystem, which explains its sustainable choice for long-term projects. 

As it adapts to modern development needs, incorporating static site generation and other contemporary practices, Thymeleaf's relevance seems secure, particularly for projects prioritizing server-side rendering. 

### Pros: 

- Ease of use with an HTML-like syntax for templates. 
- Strong integration with the Spring ecosystem. 
- Supports customization and integration of additional libraries. 

### Cons: 

- Thymeleaf's verbosity may present a learning curve. 
- Thymeleaf offers limited support for server-side logic, often needing additional frameworks or libraries. 
- Needs more time crafting custom components due to the limited functionality of out-of-the-box templates. 

## JSF (JavaServer Faces)

![JSF.png]({{strapiUrl}}/uploads/JSF_31551e7241.png)

JavaServer Faces (JSF) is a framework for building web applications with component-based, Ajax-enabled user interfaces, adhering to Java EE standards.Once a dominant force in enterprise web development, JSF has seen a shift in its standing, with popular web frameworks for Java like Spring emerging as preferred choices. However, JSF still merits its mention among the best Java Frameworks for enterprise applications. 

It's most famous for its declarative high-level approach. Thanks to its community it provides a wide range of built-in and community-developed UI components like buttons, text fields, tables, and menus. 

JSF follows the MVC pattern and uses the Facelets templating engine to build views using HTML. JSF provides built-in server-side validation and security functionalities, ensuring reliable data processing and improved protection against vulnerabilities.  

Supported by implementations like Apache MyFaces and PrimeFaces, JSF is favored in J2EE environments, especially by developers looking for an integrated approach within the Java ecosystem.  
Despite all its benefits JSF is complex, it has a steep learning curve and requires experience in web development with Java. While the quality of documentation may vary, the framework benefits from a longstanding presence in enterprise Java development. 

JSF remains a solid choice for enterprise applications, however its pace of innovation has declined in recent years. Companies invested in Java EE or Jakarta EE may continue to leverage JSF, but the framework might see limited adoption in new projects due to the increased popularity of Spring framework ecosystem.

### Pros: 

- Provides a high-level, component-based approach to UI development. 
- Offers a broad range of built-in and community-developed UI components. 
- Supported by a large community. 

### Cons: 

- Complex applications may lead to code duplication in backing beans, affecting maintainability. 
- Optimizing performance can be challenging due to the framework's inherent complexities and component lifecycles. 
- The steep learning curve associated with its complexity. 

## Spring Boot + Vaadin

![vaadin.png]({{strapiUrl}}/uploads/vaadin_20170c1371.png)

<a target="_blank" href="https://vaadin.com/">Vaadin</a> is an open-source front-end framework with pre-designed UI components using Java. 

Vaadin’s server-side approach allows you to write all your UI logic in Java, and the framework will take care of rendering it in the browser. This means you can focus on writing clean, type-safe Java code without getting bogged down by HTML, CSS, and JavaScript as opposed to the approach you’ll encounter with Spring MVC/Thymeleaf. 

Vaadin shines with its extensive collection of built-in components. These aren't your basic buttons and text fields; we're talking about sophisticated elements like grids, charts, and combo boxes, all ready to be integrated into your application with minimal fuss. It uses themes to define reusable styles and component configurations, uses Lit elements for custom web components, enhancing reusability beyond Vaadin components. 

With a proactive community alongside quality documentation and an extensive add-on ecosystem, it is accessible for developers of varying skill levels. 

Continuing to innovate, particularly with its Flow framework, Vaadin appears well-positioned to maintain relevance, especially among developers looking to create sophisticated, enterprise-grade web applications the faster way. 

### Pros

- Enables focusing on Java through its server-side approach, minimizing the need for direct front-end language interaction. 
- Provides strong community support and comprehensive documentation. 
- Supports theme-based development and offers a rich add-on marketplace to facilitate customization and extend functionality. 

### Cons: 

- Restricts detailed UI control for developers who prefer direct manipulation with HTML/CSS/JavaScript, as Vaadin abstracts away front-end complexities. 
- Limits application types with its server-side, stateful architecture by requiring sticky sessions, potentially causing uneven load distribution. 
- Leads to potentially verbose code with its imperative coding style, which can complicate codebase maintenance.

## JHipster

![jhipster.png]({{strapiUrl}}/uploads/jhipster_895defd190.png)

<a target="_blank" href="https://www.jhipster.tech/">JHipster</a> is a tool for generating, developing, and deploying applications, blending various technologies to offer a huge development platform for web applications, making it a notable mention among the best frameworks for Java. 

By using JDL (JHipster-specific domain language) you can describe all your applications, deployments, entities and their relationships in a single file (or more than one) and generate a production-ready application in no time. 

However, JHipster's generation process overwrites classes and Liquibase scripts so you have to be extra careful with changing the initial JDL model post-initial generation to avoid potential conflicts. Or you can decide to continue without using JHipster as it makes it tough to navigate the bigger the project becomes. 

JHipster's active community contributes to its extensive module marketplace, offering support and resources that bolster the developer experience, but the learning curve is quite steep for newcomers due to the overwhelming number of new technologies. 

With its agile adaptation to new technologies including Spring, JHipster remains at the cutting edge, appealing to developers seeking modern web and microservices architectures. However, its niche lies more in project initiation rather than ongoing large-scale project development. 

### Pros: 

- Generates foundational code and integrating a spectrum of technologies 
- Simplifies the discovery of new technologies and their best practices. 
- Supports a wide range of technologies and integrates them seamlessly. 

### Cons: 

- Generates excessive amounts of code, requiring thorough review and potential customization. 
- Navigating and maintaining generated projects can be challenging as they scale. 
- Has a steep learning curve for newcomers due to the multitude of integrated technologies. 

## Jmix 

![jmix_top_5_frameworks.png]({{strapiUrl}}/uploads/jmix_top_5_frameworks_2bd48fd634.png)

<a target="_blank" href="https://www.jmix.io/">Jmix</a> is an open-source platform for building full-stack enterprise-grade applications, merging Spring Boot's backend capabilities with Vaadin's component-based frontend development.  

Jmix’s declarative coding style enables rapid development of hundreds of views with minimal effort, showcasing why it has made it among the list of best Java web frameworks as of 2024.  

At the heart of its developer-friendly approach is Jmix Studio, an IntelliJ IDEA plugin further simplifying its approach to UI development. It allows developers to construct user interfaces visually, using drag-and-drop components, property editors, and wizards, providing an intuitive, centralized environment for building your application. 

Last but not least, the platform is rich in out-of-the-box features from visual components with data model binding to comprehensive modules like reporting and BPM. 

As an emerging framework, Jmix is building its community and ecosystem, leveraging the established communities of Spring and Vaadin. Its growing popularity is supported by a range of resources, including detailed documentation and an expanding array of solutions and add-ons.  

Jmix is well-positioned to grow in popularity, particularly among backend developers seeking a streamlined approach to full-stack Java application development. Its focus on rapid application development and modularity aligns well with current trends towards democratizing modern web development among software engineers of various skillset. 

### Pros: 

- Combines the backend strength of Spring with the frontend versatility of Vaadin for a unified development experience. 
- Jmix Studio enables rapid application development approach boosting software delivery. 
- Encourages the use of reusable components from the Jmix add-ons marketplace and modular application design. 
- Promotes the use of intuitive and concise code especially for defining UI thanks to its declarative style 

### Cons: 

- Lacks a large community, which might affect the availability of third-party resources and support 
- Depends on IntelliJ IDEA which limits developers who prefer using other IDEs or code editors 


We've taken a tour through Java's landscape, to wrap up our journey and see what we’ve got. 
 
Spring MVC and Thymeleaf are great and easy for static content, but adding dynamic features means a JavaScript learning curve. JSF offers a lot, but its complexity can overwhelm beginners, moreover it's somewhat detached from modern tech and architectures. Spring Boot and Vaadin is a perfect pair for enterprise applications, though its imperative coding style might add complexity. And JHipster, while a quick start, may not be ideal as your project scales up. 
 
Now, Jmix claims it merges the best parts of the ever-trending Spring Boot and Vaadin, plus it's got this tool, Jmix Studio, to help make declarative coding even easier. 

Understanding the technology’s full potential is best achieved through practical application. Therefore, let's move from words to actions and get your hands dirty with the very task that brought you here: building a web UI for CRUD operations. 

## Jmix in action  
 
Classic “Hello World” examples are good at explaining language syntax but we’re here to see the practical side of the technology, right? Given that most enterprise applications incorporate an admin panel, we’ll create one to manage employees. It will feature CRUD functionalities, a simple user interface, security features and a small service. 

For our application we’ll assume we already have a pre-existing schema with two main tables: Employee and Department.

![ER Diagram.png]({{strapiUrl}}/uploads/ER_Diagram_b9e0f0530c.png)

Note: In this section, I’ll highlight only the key benefits of working with Jmix from the developer’s perspective. To see the full step-by-step guide check out <a target="_blank" href="https://www.jmix.io/blog/development-full-stack-crud-app/">this video</a>.

## Getting Started 

Personally, when I’m new to a framework, I spend more time figuring out the structure and high-level best practices than writing code. With Jmix, you get a pre-arranged project from the get-go, setting up the basics and architectural best practices, so you can get straight to building features. 

While the folders in the project tab might remind you a Spring Boot setup, the Jmix tab takes it a step further, breaking down the project into logical sections. 

This is what your project structure in Jmix studio will look like once you’ve created your project.

![config files.png]({{strapiUrl}}/uploads/config_files_b9bb516b5f.png)

To kick things off, we'll connect our existing database. Add a new data store in Jmix and type in the credentials. Jmix generates all the necessary configurations in the properties file. Along with a dedicated config class. 

![generate data model.png]({{strapiUrl}}/uploads/generate_data_model_9008b60870.png)

The process doesn't stop there; within the same wizard, you can build the list and detail views for your entities. 

![view creation.png]({{strapiUrl}}/uploads/view_creation_83e7545fbe.png)

This approach ensures that you're not just setting up the backend but also laying out the interactive parts of your application in one go. 

By now, in just a few minutes you have created your entities, their respective controller where your business logic lives and XML descriptors that define your UI layout declaratively. 
You’ll be pleasantly surprised when you’ll hit that green button and be greeted by a full-stack application right there on your localhost:8080. 

![users.png]({{strapiUrl}}/uploads/users_f51860193d.png)

## Security 

How about security features? In Spring Security*, it could take reading a 400+ page book, consulting three forums, and a call to a friend, just to figure out where to begin. Since Jmix is built on Spring Security, do we still need to phone a friend, or is it more straightforward? 

Jmix simplifies security management with two types of roles: resource and row-level. What's even better is Jmix's declarative approach to defining permissions to your views and entities through your IDE’s UI. It's about stating what you want, not how to do it. 

![security interface.png]({{strapiUrl}}/uploads/security_interface_0601b4ed0d.png)

Note: Jmix directly uses <a href="https://docs.spring.io/spring-security/reference/servlet/authentication/architecture.html">Spring Security servlet authentication</a>, so if you are familiar with this framework, you can easily extend or override the standard authentication mechanism provided by Jmix out-of-the-box, <a href="https://docs.jmix.io/jmix/security/">see Jmix documentation</a>.

## Service 

Let’s see how easy it is to implement some functionality to our application. Our manager, John, happens to be on a mission to optimize office seating arrangements based on department sizes. To make his life easier, let’s create a button that counts employees by department in the department list view. 
Jmix Studio provides a way to scaffold useful context-dependant code using the “Code Snippets” button. Here we can choose “Data -> Load single scalar or aggregate value” and follow the menu to generate the method below. 

```

public Integer calculateEmployeeByDepartment(Department department) { 
    if(department == null) 
        return 0; 
    return dataManager.loadValue( 
                    "select count(e) from Employee e where e.department = :department", 
                    Integer.class 
            ) 
            .parameter("department", department) 
            .one(); 
} 

```

Now we have a method that loads and counts employees linked to a specific department. 

For my fellow backend devs who break out in a cold sweat at the thought of frontend coding – Jmix has got your back. It's all declarative, even on the frontend. That sound you just heard? Probably the collective sigh of relief from server-side programmers everywhere. To add a button, just a simple right-click on the Button panel in Jmix's UI tab and select 'Button'. 

![Jmix UI.png]({{strapiUrl}}/uploads/Jmix_UI_5a94a62553.png)
Below the main representation of the buttons, Jmix provides a ton of possible attributes, so you don’t have to remember them all. 

## Add-ons 

Just as Spring's ecosystem has won the hearts of developers with its range of tools, Jmix steps up with its own set of plug-and-play components called add-ons. These add-ons save you time by quickly adding new features to your app with pre-compiled code and resources. 
 
One of the widely used add-ons, for example, is the <a target="_blank" href="https://www.jmix.io/marketplace/rest-api/">Generic REST API add-on</a> built on top of <a target="_blank" href="https://spring.io/projects/spring-authorization-server">Spring Authorization Server</a>. You get to manage your data and services without the extra work of writing REST controllers. Whether you're integrating with a modern JavaScript framework for a stylish frontend or with an external system, this add-on could be your bridge with minimal fuss. 

![rest api.png]({{strapiUrl}}/uploads/rest_api_71327717c6.png)

As we can see in the screenshot above, we’re obtaining an access token and using it to get access to protected resources within our application. All we needed to do is define the roles that should be assigned to the access token in the properties file. 

## Who is Jmix for? 

Jmix is a versatile platform that caters to a wide range of B2B web applications development needs and preferences. Here's who can make the most out of Jmix: 

Ideal for those with a foundation in Spring, looking for an easy-to-learn framework. 

Suitable for backend developers moving into full-stack development without prior JavaScript experience. 

Great for developers aiming to create large-scale, enterprise-level applications efficiently – hundreds of views, excessive business logic and sophisticated permission regulation. 

An excellent choice for rapidly developing and deploying SaaS applications, standalone services or microservices as part of a larger application ecosystem. 

Perfect for modernizing legacy systems with trending features and technologies. 

<a target="_blank" href="https://www.jmix.io/is-jmix-right-for-my-project/">Still not sure if Jmix is your choice?</a>

# Conclusion 

In summing up the exploration of the best Java frameworks for web development in 2024, it's clear that each framework has its niche, carving out unique spaces in the Java ecosystem. 

Amidst these, we concluded that Jmix is more than just a java framework; it's a developer-friendly platform. 

With its ease of use and wide applicability, Jmix stands out as a high-productivity tool to those navigating the world of enterprise application development and looking for best future-proof <a target="_blank" href="https://www.jmix.io/">Java web Framework</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Video:  Full-stack CRUD App with Spring Boot and Vaadin in 15 Minutes]]></title>
            <link>https://www.jmix.io/blog/development-full-stack-crud-app</link>
            <guid>https://www.jmix.io/blog/development-full-stack-crud-app</guid>
            <pubDate>Wed, 01 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_Blog_2_Video_3251dae40e.png">In this tutorial, we'll build an admin panel for employee management ready to be deployed to production with security features, business logic, a REST API, in other words a production-ready app in under 15 minutes.]]></description>
            <content:encoded><![CDATA[In this tutorial, we take a deep dive into developing a full-stack CRUD application using Spring Boot and Vaadin with Jmix. We'll build an admin panel for employee management ready to be deployed to production with security features, business logic, a REST API, in other words a production-ready app in under 15 minutes!

You can see this tutorial on <a target="_blank" href="https://youtu.be/asKdCoIYNrg?si=T7js84ylgDwM80Xv">our youtube channel</a>.

<youtube data-video-id="asKdCoIYNrg?si=T7js84ylgDwM80Xv"></youtube>

## Timestamps:

+ <time-code data-time="0:00"> General information
+ <time-code data-time="0:25"> New project
+ <time-code data-time="2:52"> Data model
+ <time-code data-time="5:09"> Security features
+ <time-code data-time="8:47"> Business logic and UI development
+ <time-code data-time="12:13"> Generic REST API add-on


<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[New Jmix course on Udemy]]></title>
            <link>https://www.jmix.io/blog/free-course-rad-with-jmix</link>
            <guid>https://www.jmix.io/blog/free-course-rad-with-jmix</guid>
            <pubDate>Wed, 01 May 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/ddc2c2143f29dcaf996dcc140e7a87e645f3b137_8cb194bb7a.png">Jmix is thrilled to present a new free Udemy course "Rapid Application Development with Jmix".]]></description>
            <content:encoded><![CDATA[Jmix is thrilled to present a new **free** Udemy course "<a target="_blank" href="https://www.udemy.com/course/rapid-application-development-with-jmix/">Rapid Application Development with Jmix</a>". Designed for both new and professional developers, this course offers a comprehensive dive into efficient full-stack web application creation using Jmix.



## What you’ll learn

- Construct full-stack web applications with Java and Jmix.
- Utilize Jmix Studio and its visual toolkit to simplify data modeling and DDL operations.
- Dive into various open-source Java technologies that are the cornerstone of Jmix.
- Cover the fundamentals of application security and deployment.

## Who this course is for

- Novice developers ready to develop a real web application while learning core concepts.
- Skilled developers searching for innovative tools to boost their efficiency.
- Anyone interested in creating web applications powered by open-source technologies.


<a target="_blank" href="https://www.udemy.com/course/rapid-application-development-with-jmix/">Enroll now</a> and start your journey to becoming proficient in Jmix.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Visualize data in your App with Jmix Maps]]></title>
            <link>https://www.jmix.io/blog/visualize-data-with-jmix-maps</link>
            <guid>https://www.jmix.io/blog/visualize-data-with-jmix-maps</guid>
            <pubDate>Fri, 05 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_Blog_Maps_06_3b5b260760.png">Discover how to embed interactive maps into your web applications using the Jmix Maps add-on. Follow simple steps to set up an interactive map and define its behavior using Java and XML.]]></description>
            <content:encoded><![CDATA[&nbsp;]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What is Rapid Application Development]]></title>
            <link>https://www.jmix.io/blog/rapid-application-development</link>
            <guid>https://www.jmix.io/blog/rapid-application-development</guid>
            <pubDate>Mon, 01 Apr 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Servisnye_uslugi_v_Jmix_1200h630_73f9c4aa48.png">Rapid application development (RAD) is a development approach focusing on designing and prototyping stage for the purpose of getting instant user feedback.]]></description>
        </item>
        <item>
            <title><![CDATA[ Jmix Premium Features Now Free for Small Projects]]></title>
            <link>https://www.jmix.io/blog/free-jmix-studio</link>
            <guid>https://www.jmix.io/blog/free-jmix-studio</guid>
            <pubDate>Sun, 31 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_Blog_2_Free_Studio_c0d9990155.png">We're unlocking Jmix RAD plan for all small projects with the release Jmix 2.2.]]></description>
            <content:encoded><![CDATA[Starting with Jmix 2.2 release in February 2024, every developer will be able to use Studio RAD features for free forever, but with limitations on the project size:

Max entities – 10;
Max roles – 10;
Max views – Unlimited :)

### What happens if my project exceeds 10 entities and roles?

The Studio will automatically transition out of the Jmix Free Plan, allowing you to proceed with your development unrestricted. However, you will no longer have access to the Jmix RAD features.

### Why does this matter?

This opens up the opportunity for developers with small projects and startups to use a powerful backend development tool for free. Now, everyone can start working with Jmix, experimenting, and developing their ideas without worrying about licensing fees.

### Join our community

This is more than an update; it's an invitation. Ready to take advantage of Jmix premium features for your project? Click <a href="https://www.jmix.io/get-started/">here</a> to learn more and get started. Let's turn your ideas into reality, faster and free from cost.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: Embedding Interactive Maps into Java Web App with Jmix]]></title>
            <link>https://www.jmix.io/blog/maps-webinar</link>
            <guid>https://www.jmix.io/blog/maps-webinar</guid>
            <pubDate>Mon, 25 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/maps_webinar_d714143136.png">In this webinar we dive into integrating interactive maps, visualizing geospatial data, and boosting user navigation in your web apps. ]]></description>
            <content:encoded><![CDATA[Embedding a map into an application has become a common task across various business domains, as it not only enhances the effectiveness of data presentation—like clearly visualizing sales regions for better market insight—but also significantly improves user experience by simplifying the navigation and search for example, for local branches or services.

In this video, we show how to embed interactive maps into your web applications using the Jmix Maps add-on. We guide you through the easy steps to set up an interactive map and define its behavior using Java and and XML.
 You can see recording of webinar on <a target="_blank" href="https://youtu.be/ZL0m453fLks">our youtube channel</a>.

<youtube data-video-id="ZL0m453fLks"></youtube>

## The topics on webinar agenda:

+ <time-code data-time="0:00"> Introduction
+ <time-code data-time="2:11"> What we are going to build
+ <time-code data-time="5:21"> How to store coordinates
+ <time-code data-time="12:06"> Locations
+ <time-code data-time="12:41"> Coordinate serialization
+ <time-code data-time="15:16"> Location lookup view
+ <time-code data-time="25:36"> Interactive Map
+ <time-code data-time="33:06"> Feature styling
+ <time-code data-time="39:11"> Useful links


<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: What's new in Jmix 2.2]]></title>
            <link>https://www.jmix.io/blog/whats-new-in-jmix22</link>
            <guid>https://www.jmix.io/blog/whats-new-in-jmix22</guid>
            <pubDate>Thu, 14 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/jmix_2_2_01_925acbf2bd.png">In this webinar, we talked about new features and improvements in Jmix framework and Studio 2.2. ]]></description>
            <content:encoded><![CDATA[In this webinar, we talked about new features and improvements in Jmix framework and Studio 2.2. We also took a closer look at the new features and discussed future plans.  You can see recording of webinar on <a target="_blank" href="https://youtube.com/live/vyyAfevlzM8">our youtube channel</a>.

<youtube data-video-id="vyyAfevlzM8"></youtube>

## The topics on webinar agenda:

+ <time-code data-time="0:23"> Introduction
+ <time-code data-time="1:30"> What's new on Jmix web-site
+ <time-code data-time="2:48"> Community growth plans for 2024: Free Jmix Studio RAD for small projects, Jmix AI assistant, Video guides and tutorials, Jmix course for beginners, Documentation improvements 
+ <time-code data-time="7:43"> Jmix marketplace for commercial add-ons and solutions
+ <time-code data-time="8:45"> BPA platform based on Jmix
+ <time-code data-time="27:25"> What's new in Jmix 2.2
+ <time-code data-time="27:42"> Charts add-on
+ <time-code data-time="30:45"> Maps improvements
+ <time-code data-time="33:46"> RichTextEditor Component
+ <time-code data-time="35:05"> Main view Improvements
+ <time-code data-time="40:18"> DataGrid Improvements
+ <time-code data-time="43:27"> Collection Properties in Generic Filter
+ <time-code data-time="45:57"> Adding Components Using Wizards
+ <time-code data-time="47:27"> Test Scaffolding
+ <time-code data-time="48:57"> Reduced Build Time
+ <time-code data-time="49:40"> Updated Dependencies
+ <time-code data-time="50:25"> Future releases


<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 2.2 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-2-2-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-2-2-is-released</guid>
            <pubDate>Mon, 04 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_2_0_1611x720_25cfc2ca4e.png">Overview of the new features and important changes of the Jmix 2.2 feature release.]]></description>
            <content:encoded><![CDATA[The most recent iteration of Jmix, version 2.2, has just been released.  In this article, we'll delve into the fresh features and improvements introduced in this update.

To find out more details and guidance on migrating, make sure to visit the <a href="https://docs.jmix.io/jmix/2.2/whats-new/index.html" target="_blank">What's New</a> page in the documentation.

## Charts Add-on

Perhaps the most notable new feature of Jmix 2.2 is the long awaited Charts add-on. It integrates <a href="https://echarts.apache.org" target="_blank">Apache ECharts</a>, an open-source JavaScript charts library, into Jmix UI. Now you can use the full power of ECharts by configuring it in XML or Java in your Jmix application and easily connect to your data on the server side as the other UI components.

For example, having a `VehicleCount` entity which stores the number of different vehicles by year in the `cars`, `motorcycles`, `bicycles` and `year` attributes, you could configure a chart for data visualization as follows:

```xml
<data>  
    <collection id="vehiclesDc"  
                class="com.company.demo.entity.VehicleCount">  
        <fetchPlan extends="_local"/>  
        <loader id="vehiclesDl" readOnly="true">  
            <query>  
                <![CDATA[select e from VehicleCount e order by e.year]]]]><![CDATA[>  
            </query>  
        </loader>  
    </collection>  
</data>
<layout>
	<charts:chart id="chart">  
	    <charts:dataSet>  
	        <charts:source dataContainer="vehiclesDc"  
	                       categoryField="year"  
	                       valueFields="cars motorcycles bicycles"/>  
	    </charts:dataSet>  
	    <charts:series>  
	        <charts:bar name="Cars"/>  
	        <charts:bar name="Motorcycles" stack="stack"/>  
	        <charts:bar name="Bicycles" stack="stack"/>  
	    </charts:series>  
	    <charts:xAxes>  
	        <charts:xAxis/>  
	    </charts:xAxes>  
	    <charts:yAxes>  
	        <charts:yAxis>  
	            <charts:axisLabel formatter="{value}"/>  
	        </charts:yAxis>  
	    </charts:yAxes>  
		<charts:title text="Vehicles" subtext="By Year"/>  
		<charts:legend/>
	</charts:chart>
```

As you can see, the chart connects to a data container using the `source` element and defines how to display data in the `series` element. The resulting chart is shown below:

![charts-1.png]({{strapiUrl}}/uploads/charts_1_b1979dbd2b.png)

We have tried to make the XML and Java chart API as close as possible to the native JavaScript API of ECharts, making it straightforward to configure a chart in Jmix by referring to the comprehensive ECharts documentation.

The Charts add-on is available for free on the <a href="https://www.jmix.io/marketplace" target="_blank">Marketplace</a> and can be used in any project based on Jmix 2.2.

## Maps Add-on Improvements

The Maps add-on has received new important features: ability to display MultiPoint, MultiLine and MultiPolygon geometries, heatmap layers, and clustering.

A MultiPolygon is just a collection of polygons in a single geometry. In the example below, we create a multipolygon consisting of two rectangles:

```java
private void addMultiPolygon(VectorSource vectorSource) {  
    GeometryFactory factory = GeometryUtils.getGeometryFactory();  
    Polygon polygon1 = factory.createPolygon(  
            factory.createLinearRing(new Coordinate[]{  
                    new Coordinate(15.5, 38.9),  
                    new Coordinate(15.5, 44.9),  
                    new Coordinate(9.5, 44.9),  
                    new Coordinate(9.5, 38.9),  
                    new Coordinate(15.5, 38.9)}));  
    Polygon polygon2 = factory.createPolygon(  
            factory.createLinearRing(new Coordinate[]{  
                    new Coordinate(20.7, 40.9),  
                    new Coordinate(26.7, 40.9),  
                    new Coordinate(26.7, 34.9),  
                    new Coordinate(20.7, 34.9),  
                    new Coordinate(20.7, 40.9)}));  
    MultiPolygon multiPolygon = factory.createMultiPolygon(new Polygon[]{polygon1, polygon2});  
    vectorSource.addFeature(new MultiPolygonFeature(multiPolygon));  
}
```

It will be shown on the map as follows:
![maps-1.png]({{strapiUrl}}/uploads/maps_1_6276f5ffbf.png)

The clustering feature allows you to display a large number of markers on a map by consolidating them. In the following example, the map shows the most famous cities founded by the Romans:

![maps-2.png]({{strapiUrl}}/uploads/maps_2_f066954ef5.png)

This is achieved simply by wrapping the vector data source into the `cluster` element in view XML:
```xml
<maps:geoMap>  
    <maps:layers>  
        <maps:tile>  
            <maps:osmSource/>  
        </maps:tile>  
        <maps:vector id="cityLayer">  
            <maps:cluster distance="30">  
                <maps:dataVectorSource dataContainer="citiesDc" property="point"/>  
            </maps:cluster>  
        </maps:vector>  
    </maps:layers>  
    <maps:mapView centerY="41.9" centerX="12.48" zoom="4.5"/>  
</maps:geoMap>
```

The same data can be visualized in a heatmap, where the values are represented by color:

![maps-3.png]({{strapiUrl}}/uploads/maps_3_0fca314669.png)

The heatmap is configured by a special `heatmap` layer with its own data source connected to the same data container:
```xml
<maps:geoMap>  
    <maps:layers>  
        <maps:tile>  
            <maps:osmSource/>  
        </maps:tile>  
        <maps:heatmap radius="15">  
            <maps:heatmapDataVectorSource dataContainer="citiesDc" property="point"/>  
        </maps:heatmap>  
    </maps:layers>  
    <maps:mapView centerY="41.9" centerX="12.48" zoom="4.5"/>  
</maps:geoMap>
```

## Improvements in BPM

In order to shorten the feedback loop when developing processes in Studio, we have implemented hot deployment of process definitions into the running application. You can find the *Hot Deploy Process* button in the top panel of the BPMN designer. The application prints a message in the log when a process is deployed successfully:

![bpm-1.png]({{strapiUrl}}/uploads/bpm_1_a1facba6d5.png)

The process form wizard in Studio can now generate a form for the start event. Such a form will contain a *Start process* button which invokes the process engine API.

This wizard also contains the new *Process form for entity instance* item in the *Form template* dropdown. If you choose this option, the wizard will allow you to select or create a variable of the *Entity* type. The resulting process form will contain a data container and a field for editing the selected entity.

## RichTextEditor Component

The new `richTextEditor` component based on the <a href="https://quilljs.com" target="_blank">Quill</a> JavaScript library allows you to edit text with formatting and save it as HTML:

![rich-text-editor-1.png]({{strapiUrl}}/uploads/rich_text_editor_1_1c7ef42c06.png)

The component is data-aware and can be easily connected to your data model:
```xml
<richTextEditor id="descriptionField" width="100%"  
                dataContainer="stepDc" property="description"/>
```

## Improvements in Main View

The new `menuFilterField` component allows users to filter main menu items. 

You just need to put  the filter field somewhere on the view and connect it to `listMenu`:
```xml
<menuFilterField menu="menu"
                 placeholder="Search..." classNames="ms-s me-s"/>
<nav id="navigation" classNames="jmix-main-view-navigation" ariaLabel="msg://navigation.ariaLabel">
    <listMenu id="menu"/>
</nav>
```

The menu filtering in action:

<img src="{{strapiUrl}}/uploads/menu_filter_3f7575e4c5.gif" width="500">

The next improvement related to the main view is the ability to declaratively define the content when no child views are open. Use the `initialLayout` element of the `appLayout` component:
```xml
<appLayout>
    <navigationBar .../>
    <drawerLayout .../>
    <initialLayout>
        <h2 text="Hello world!"/>
    </initialLayout>
</appLayout>
```

Then your application will look as follows:

![initial-layout.png]({{strapiUrl}}/uploads/initial_layout_b85fb2fa00.png)

And probably the most anticipated enhancement in this area is the horizontal main menu:

![top-menu.png]({{strapiUrl}}/uploads/top_menu_16d7d71a39.png)

It's implemented by the `horizontalMenu` component which obtains the menu structure from the same `menu.xml` descriptor. So you can easily replace the standard vertical `listMenu` by the top horizontal menu at any moment in your project. The simplest way to do it is to click *New → View* and select the *Main view with top menu* template. If you select the *Use as default main view* checkbox on the second step of the wizard, Studio will set the new main view in the `jmix.ui.main-view-id` application property and in the `layout` attribute of the `@Route` annotation for all existing views, for example: 

```java
@Route(value = "users", layout = MainViewTopMenu.class)
```

As a result, the new main view with the horizontal menu will work as expected as soon as you run the application.

## DataGrid Improvements

Double-click in a data grid row now opens a detail view or, in lookup mode, finishes the selection. Desktop users will find it very convenient because they do not need to select a row and then clicking a button or menu item.

We also finished the work on the filter in column headers: it can now be reflected in URL to provide a deep link and to save the view state when navigating to a detail view and back. Use the new `dataGridFilter` element of the `urlQueryParameters` facet for this.

One more useful feature is the new `gridColumnVisibility` component, which enables users to hide and show grid columns:

![data-grid-column-visibility.gif]({{strapiUrl}}/uploads/data_grid_column_visibility_793253d664.gif)

## Collection Properties in Generic Filter

Previously, to filter an entity by its collection attribute using the `genericFilter` component, one had to define a JPQL condition with `join` and `where` clauses. Apparently, that was not something easily achievable for an end user.

Now the filtering by to-many references and their nested attributes is as simple as with to-one references: they are shown in the *Add condition* dialog of the generic filter and the required JPQL conditions are generated by the framework automatically.

In the following example, the list of users is filtered by the `completedDate` attribute of the linked `steps` collection:

![generic-filter-1.png]({{strapiUrl}}/uploads/generic_filter_1_c5ff092430.png)

![generic-filter-2.png]({{strapiUrl}}/uploads/generic_filter_2_25c7615114.png)

## Reduced Build Time

While the hot deploy technology drastically shortens the feedback loop when developing the user interface, it does not apply to the development of business logic. Therefore, quick application restart during development remains crucial.

In Jmix version 2.2, the entity enhancing step, which consumes a significant amount of time during the build, will only be executed if there have been changes to the data model since the last build. Consequently, if you are working on Spring beans without modifying the entities, the build and restart process is now much faster than it was previously, especially in projects with large data models.

## New Code Snippets

If you include Reports, Email sending, BPM or Notifications add-ons in your project, you will find new code snippets related to the API of these add-ons.

For example, if you want to run a report when a user clicks a button, you can generate the button click listener and then drag-and-drop the *Run report using UiReportRunner* snippet to the listener. Studio will prompt you to specify the report you wish to run and will generate the corresponding code for you:

![reports-code-snippet.gif]({{strapiUrl}}/uploads/reports_code_snippet_7b88851f7e.gif)

The generated code just works and can be a good starting point for further customization.

## Adding Components Using Wizards

As the collection of UI components expands, it becomes increasingly challenging for newcomers to locate a suitable component for a specific task.

So we decided to provide another, even more *declarative* way of creating UI views. Instead of selecting a component from the *Add Component* palette and configuring it, developers can start a wizard that prompts a series of questions. The wizard then generates an entire fragment containing preconfigured visual and data components.

In fact, the Studio included such wizards before for DataGrid and data containers, but these wizards started only when you explicitly selected the corresponding component from the palette. Now you can be unaware about existence of a particular component and just select a wizard that according to its name could accomplish your task.

In the following screencast, the *Edit entity attributes* wizard creates a `formLayout` with fields connected to a data container:

![edit-entity-attributes-wizard.gif]({{strapiUrl}}/uploads/edit_entity_attributes_wizard_2a362846cb.gif)

This feature is currently rather experimental and we plan to enhance it in the future by adding more wizards and making them more useful in various use cases.

## Test Scaffolding

When you open a project in the new Studio, you will immediately see the *Tests* item in the Jmix tool window. Double-clicking on this item will take you to the *Project* tool window and position in the `src/test/java` directory.

The *New → Advanced → Integration Test* and *UI Integration Test* actions allow you to quickly generate stubs for your business logic and UI integration tests.

## Free Studio for Small Projects

And the last but not least: now the premium RAD features of Studio are available for free in small projects with up to 10 entities and roles. This means that you can access all visual tools for learning, experimenting, and creating pet projects or commercial applications without needing an active commercial or trial subscription. The only limitation is that these projects should not require large data and security models.

We expect that the free tooling will make it easier for developers to learn and adopt the technology, thus making Jmix accessible to a broader audience.

## What's next?

In the next feature release in June 2024, we plan to implement an integration with <a href="https://superset.apache.org" target="_blank">Apache Superset</a>, the leading open-source data visualization platform. 

On the Studio side, we are going to provide an approach for aggregating Liquibase changelogs and actions for quick conversion of similar UI components, such as `entityPicker` and `entityComboBox`.

As usual, we will dedicate a significant amount of time to fixing bugs, adding small features, and making performance improvements.

Our detailed roadmap for future releases is available as a <a href="https://github.com/orgs/jmix-framework/projects/5" target="_blank">GitHub project</a>. Patches for the current version 2.2 will be released approximately once a month to ensure regular updates.

We appreciate your feedback on our <a href="https://forum.jmix.io" target="_blank">forum</a>, and we are thankful to all those who have submitted pull requests and shared their ideas, suggestions, and bug reports!
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Java Web App Reporting: Jasper Report vs Jmix Reports]]></title>
            <link>https://www.jmix.io/blog/jmix-report-vs-jasper-reports</link>
            <guid>https://www.jmix.io/blog/jmix-report-vs-jasper-reports</guid>
            <pubDate>Fri, 01 Mar 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_Blog_Reports_41cc2e90b9.png">Unlike a standalone reporting library, the Jmix Reports Addon is a complete and ready-to-use module.]]></description>
        </item>
        <item>
            <title><![CDATA[Jmix 2023 Recap and 2024 Roadmap]]></title>
            <link>https://www.jmix.io/blog/recap-2023-roadmap-2024</link>
            <guid>https://www.jmix.io/blog/recap-2023-roadmap-2024</guid>
            <pubDate>Thu, 29 Feb 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_recap_BLOG_cfe5b84222.png">One more year has gone, so it’s time for the traditional recap of what the team was working on and what we plan for the 2024.]]></description>
            <content:encoded><![CDATA[# 2023 in review

Well, it’s time to sum up the main achievements of the Jmix team in 2023 and share our thoughts about the product’s future. Undoubtedly, the main accomplishment of 2023 was that we finally completed the transition to the latest Vaadin 24 and Spring Boot 3 in Jmix 2.0. That was a challenging path, and we hadn’t entirely anticipated all the difficulties we encountered. At the beginning of 2023, we even expected to maintain the ability for developers to use both options – Classic UI and Flow UI – in their Jmix projects. Unfortunately, this decision was heavily impacted by the upgrade from Spring Boot 2.7 to Spring Boot 3, accompanied by the javax to jakarta namespace change. This issue left no room for using both UI options in a single Jmix project. In order to support community members who had already launched projects with Jmix 1.X, we announced that it will become a Lont-Term Support (LTS) version, with the promise to transfer compatible innovations from further Jmix 2.X releases. You can find details in the dedicated <a target="_blank" href="https://www.jmix.io/blog/extended-support-for-classic-ui/">blog post</a>.

Good news – we’ve made a quantum leap with the new Vaadin 24 UI, bringing all the advantages of this great technology to the Jmix community. By the end of 2023, we had almost implemented the most popular UI components and nearly secured the existing developer experience for creating view layouts and events handling.

Nowadays we’re working hard on introducing Charts and enhancing Maps functionality by the end of Feb 2024. The top-rated add-ons have also migrated to the new Flow UI, and now you can find them available in the <a target="_blank" href="https://www.jmix.io/marketplace/">marketplace</a>: <a target="_blank" href="https://www.jmix.io/marketplace/reports/">Reports</a>,  <a target="_blank" href="https://www.jmix.io/marketplace/bpm/">BPM</a>,  <a target="_blank" href="https://www.jmix.io/marketplace/webdav/">WebDAV</a>, <a target="_blank" href="https://www.jmix.io/marketplace/business-calendars/">Business Calendar</a>, <a target="_blank" href="https://www.jmix.io/marketplace/notifications/">Notifications</a>, <a target="_blank" href="https://www.jmix.io/marketplace/quartz/">Quartz Scheduler</a>, <a target="_blank" href="https://www.jmix.io/marketplace/search/">Search</a>, and <a target="_blank" href="https://www.jmix.io/marketplace/dynamic-attributes/">Dynamic Attributes</a> . With Flow UI, Jmix developers gain access to a modern and highly customizable technology for creating enterprise server-side UIs powered by web components, along with the advantage of using CSS styling. There’s no longer a need to perform exhausting operations to wrap up external JS components for their implementation in application views. You can find live examples with code in <a target="_blank" href="https://demo.jmix.io/ui-samples/sample/custom-component-js-library">UI Samples</a>. All Jmix views are responsive by default, with the ability to determine the visual style of the view layout based on the container’s size, utilizing a dedicated <a target="_blank" href="https://demo.jmix.io/ui-samples/sample/form-layout-responsive-steps">responsiveSteps</a> tag in the descriptor.

Despite our earlier promises, we decided to suspend our research in the area of mobile UI development support in Jmix. After performing R&D around Flutter UI, we found it feasible. However, we considered it a risky area for further investment. Speaking to development teams worldwide in 2022-2203, we encountered a vast array of technologies they’ve become accustomed to for their mobile projects. Thus, Flutter still doesn’t appear to be a technology most teams are likely to adopt shortly. In contrast, on the server side, when it comes to enterprise software development in Java, there isn’t too much choice: Spring Boot and JPA are almost set. And this is exactly what Jmix excels at, especially in cases where you find Java server-side UI development more appealing than using JavaScript for your project. A significant advantage of implementing Vaadin 24 is that Jmix now has out-of-the-box support for PWA (Progressive Web Applications). In combination with business-oriented UI components library, you can create web applications that look native on mobile devices, offering the same developer experience. Please note, though, that it doesn’t support offline mode.

In 2023, we devoted significant effort to enhancing support for BPM application development in Jmix Studio. Jmix developers have got a single development platform based on IntelliJ IDEA Community Edition that supports all steps from process model to deployment:

- Design or import BPMN 2.0 diagrams;
- Generate process forms for user tasks;
- Connect service tasks with project-specific Spring beans;
- Deploy process within the application runtime, powered by an embedded Flowable BPM engine;
- Conduct business process test runs, including tools for fine tuning and monitoring.

And all these operations can be performed seamlessly without the need for additional tools or effort. You can find more details on this by visiting the following <a target="_blank" href="https://www.jmix.io/blog/bpm-tool/">webinar</a>. We’ve received encouraging feedback from the community on this development.

Finally, we introduced a useful feature of Quick Cloud Deployment. It allows you to deploy Jmix application to AWS with just a few clicks. Jmix Studio provides a guided path from configuring the deployment unit to getting a link to the deployed web application instance. This feature reduces the time and effort required to set up and run your application in the AWS cloud environment. Developers find it particularly attractive during the early stages of project development.

## 2023 in numbers

We’re pleased to report that the improvements made to Jmix in 2023 have significantly increased the technology’s popularity across various markets, with the most notable growth observed in Central Asia, China, Eastern Europe, Italy, Malaysia, North Africa, Spain, Switzerland, and Vietnam.

- **2023 Website visitors:** 111 585, 1.5% up ↑
- **2023 Forum visitors:** 59 300, 104% up ↑
- **2023 Docs visitors:** 43 900, 49% up ↑
- **Linkedin followers:** 1055, 65% up ↑
- **Monthly Active Users** increased by 27% ↑

Furthermore, we’re proud to announce that in 2023, nearly 85% of our active commercial subscriptions were renewed. This achievement sets a new record for Jmix, demonstrating the high level of confidence our enterprise customers have in the technology. This support significantly contributes to the financial backing of Jmix further development plans.

# Product plans for 2024

As we completed the transition to the updated technology stack, our team will primarily focus on developing new features for Jmix 2.X and enhancing educational resources for developers and newcomers. In 2024, we decided to prioritize the following development initiatives:

— Implement tooling and framework support for working with external data sources. We aim to enable Jmix support for automatic Java client generation based on the OpenAPI specification and mapping the APIs to the DTOs. We anticipate that this will simplify manipulating data from external sources in Jmix business logic and UI.

— Improve visual tools for working with the data model and UI. We understand that developers often face challenges when modifying previously generated views or starting a new layout from scratch. Therefore, we’re committed to making improvements in visual tooling, which should simplify fine-grained layout customizing. Moreover, we plan to introduce ER-model visualizing, a feature frequently requested by our community to analyze complex data models.

— Make Jmix data repositories available in views. In 2023, we introduced this feature but didn’t complete the path for connecting data from repositories with the UI. We’re determined to finalize the entire concept and make it developer-friendly.

— Enrich the UI components library for better end-user UX supporting a declarative layout design approach. We plan to create the GroupTable, Pagination, and Calendar UI component within Flow UI technology. Additionally, we intend to introduce enhanced support for declarative configuration of VirtualList component in the view descriptor.

— Introduce add-ons for business analytics - Dashboard and Pivot Table. Configurable tools for business analysis are essential for B2B applications, and we aim to enhance this functionality with the popular open-source technology – Apache Superset. Our R&D was completed in 2023, and it looks very promising.

— Position Jmix as a full-featured Business Process Automation (BPA) platform capable of meeting modern enterprise requirements:

- Support for developing applications using both an embedded and a standalone open-source BPM engine: Flowable in 2024 and Camunda support in 2025.
- Create a new customizable process Task List add-on, which can communicate tasks queue for both types of BPM engines – embedded and standalone.
- Create a new Process Monitoring tool that provides an Admin UI for managing process instances running on both types of BPM engines - embedded and standalone.

Java developers eager to adopt an open-source BPM engine for their next process automation project will find a ready-to-use backend platform and tools with a set of essential process management tools – Task List and Process Monitoring.

You may see that we’re committed to our strategy of maximizing performance for Java developers and teams when building modern B2B full-stack web-applications.


# Community work plans for 2024

Another important aspect we’re going to strengthen is the developer on-boarding process. We understand that this is the key to spreading Jmix technology worldwide and scaling the community. In 2024, we’re planning to take a significant step forward in simplifying the on-boarding path for newcomers. Here are major highlights:

— **Jmix AI Assistant** – a web-based, LLM-powered chatbot will help find answers in seconds. It supports multiple languages. We have trained the AI Assistant using the documentation, forum, and UI samples knowledge base, and results look very promising. The Early Access Program (EAP) will be launched in Q2. We hope to make it available for everyone in Q3.

— **Jmix Basics Free Learning Course at Udemy**. Our training team has decided to focus on the Udemy learning platform and create a comprehensive course covering all basic topics. We anticipate its launch in April 2024.

— **Free Jmix Studio RAD Subscription**. Starting with Jmix 2.2 release in February 2024, every developer will be able to use Studio RAD features for free forever, but with limitations on the project size:

- **Max entities – 10;**
- **Max roles – 10;**
- **Max views – Unlimited :)**

If your project exceeds 10 entities and roles, the Studio will automatically transition out of the Jmix Free Plan, allowing you to proceed with your development unrestricted. However, you will no longer have access to the Jmix RAD features.

— **Documentation Improvements**. We plan to reveal the core concepts of the Jmix platform in a dedicated section and enrich add-ons description with specific tutorials showcasing use cases and related technologies. You can check the first results of the revamping the Maps add-on section of the <a target="_blank" href="https://docs.jmix.io/jmix/maps/index.html">documentation</a>.

— **More Sample Applications and Video Content**. We plan to migrate Jmix Bookstore to Jmix 2.X and produce more video content demonstrating popular development tips.

And the last item, but not less important. Since the launch of the CUBA Platform, we’ve dreamt about opening the Jmix Marketplace for commercial third-party add-ons and solutions. During 2023, we discovered many useful apps created by our partners worldwide, and it looks like a promising growth area. In Q2, we’re planning to roll out our first deliverable solution – Timesheets. This is a relatively small but super important app for tracking time spent across different projects in teams. We believe this will encourage our partners to share their add-ons and solutions, creating new connections across the Jmix customer network.


# Jmix 1.X and CUBA Platform support

Jmix 1.X platform will receive updates with the Jmix 1.6 release by mid-2024 as planned.

According to our support policy, we will provide the CUBA Platform with updates of third-party dependencies and bug fixes. Please keep in mind that in March 2025, the free maintenance period of CUBA Platform ends. In order to assist the community with migration to Jmix from the CUBA Platfrom, our service team is preparing additional resources to share valuable information about existing transition successful experiences. We plan to introduce a webinar and a whitepaper on this topic in Q2 2024. Recently, we have received questions concerning further support for Jmix 1.X and the CUBA Platform. You may find answers on most of them in the dedicated FAQ section.

That’s all for now. I hope to report that almost everything from the list has been accomplished as planned at the beginning of 2025! See you soon.

### Stay connected and be productive.


# FAQ CUBA Platform and Jmix 1.X maintenance

***What should you do if you still have applications build with CUBA Platform?***

Plan to upgrade to the latest Jmix version. If you cannot upgrade, make sure you run your application in a safe environment behind a firewall.

***How would you get support for applications on CUBA Platform after 2025?***

Call us.

***How will we fix CUBA Platform and Jmix 1.X vulnerability issues within a free LTS support period?***

The free support period for CUBA and Jmix LTS versions assumes that we fix critical security vulnerabilities and data loss bugs by providing new patch releases. If the problem is in our own code, we have complete control over the situation and can quickly resolve the issue. But if the problem is related to a third-party dependency, things become much more complicated. We had to wait until the vendor of the dependency publishes a new version with a fix, and then try to integrate that version into Jmix. It's not always possible, because sometimes issues are fixed in a new major version incompatible with the Jmix LTS version.

For example, Jmix 1.5 uses Spring Web 5.3, which has a major vulnerability related to Java deserialization of untrusted data. The Spring team has fixed it in 6.0 simply by removing the vulnerable code. But Jmix 1.x cannot use Spring 6.x because the latter requires jakarta namespace and involves many other major changes. So, on one hand, this vulnerability will always remain in Jmix 1.x, but on the other hand, it cannot be exploited in Jmix applications, because the vulnerable Spring code is never actually used.

In general, our approach to dealing with security vulnerabilities is the following:

- If the vulnerability is in Jmix code, we fix it and release a patch version.
- If the vulnerability is in a third-party dependency and there is a newer version of the dependency that we can integrate, we update the dependency and release a patch version.
- Otherwise, we analyze the real impact of the vulnerability on Jmix applications and provide recommendations to overcome possible consequences or at least to minimize the risk.
- We will also investigate any penetration test report with a scenario demonstrating a vulnerability to a Jmix application. We will do our best to provide solutions to real-world security problems, regardless of their source.

***What have we promised by free LTS platform support?***

See <a target="_blank" href="https://www.jmix.io/framework/versioning/">Jmix Release Versioning</a>: "After the active support phase, a feature release moves to the maintenance phase. Maintenance means fixing critical security vulnerabilities and data loss bugs. Fixes are provided in a new patch release of the supported version." "If a critical security vulnerability or a data loss bug is caused by an external third-party dependency, we update the dependency if there is a newer fixed version. There may be cases when we may be unable to include the newer version of a dependency if architectural changes for that version prevent its usage in Jmix or the effort required to integrate the new version exceeds reasonable commercial efforts."

***What should you do if you’ve already started the project with Jmix 1.X?***

You should plan to upgrade to the latest Jmix version.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: What's new in Jmix 2.1]]></title>
            <link>https://www.jmix.io/blog/whats_new_in_jmix_2_1</link>
            <guid>https://www.jmix.io/blog/whats_new_in_jmix_2_1</guid>
            <pubDate>Fri, 24 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/what_new_Jmix_2_1_9a908e458d.png">In this webinar, we talked about new features and improvements in Jmix framework and Studio 2.1. ]]></description>
            <content:encoded><![CDATA[In this webinar, we talked about new features and improvements in Jmix framework and Studio 2.1. We also took a closer look at the new features and discussed future plans.  You can see recording of webinar on <a target="_blank" href="https://youtube.com/live/u79fZ-zX5Fk">our youtube channel</a>.

<youtube data-video-id="u79fZ-zX5Fk"></youtube>

## The topics on webinar agenda:

+ <time-code data-time="0:22"> From Cuba 7.2 to Jmix 2.1 Recap
+ <time-code data-time="12:33"> What's new in release Jmix 2.1: Overview
+ <time-code data-time="12:58"> New add-ons: Dynamic Attributes, Notifications, Search, WebDav, Maps (Preview), Bulk Editor, JMX Console
+ <time-code data-time="26:07"> BPM improvements
+ <time-code data-time="28:25"> Data Grid improvements
+ <time-code data-time="34:09"> UI improvements. New components: VirtualList, HTML. New facets: Settings, Timer. Fetching Items in DropDowns.
+ <time-code data-time="41:02"> Studio improvements: View designer improvements, Injection by code completion, Support for data repositories, Commenting data model
+ <time-code data-time="47:20"> Future releases: Charts add-ons, Completed maps add-on, ReachTextArea component, Hot deployment of BPM definitions, Data repositories in UI views
+ <time-code data-time="49:30"> What does Jmix stand for?
+ <time-code data-time="52:00"> Jmix ranks among the top 5 Java web frameworks in G2 Grid for Java Framework
+ <time-code data-time="53:01"> A single tool to deliver process-driven application
+ <time-code data-time="55:01"> Q&A session


<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 2.1 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-2-1-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-2-1-is-released</guid>
            <pubDate>Tue, 14 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/2_1_c706f70b9a.png">Overview of the new features and important changes of the Jmix 2.1 feature release.]]></description>
            <content:encoded><![CDATA[The new Jmix version 2.1 has been released recently. In this blog post, we'll explore the new features and enhancements that have been included in this release.

For full details and upgrade instructions, make sure to visit the <a href="https://docs.jmix.io/jmix/2.1/whats-new/index.html" target="_blank">What's New</a> page in the documentation.

## New Add-ons

We've implemented a bunch of add-ons which were previously available in Jmix v.1 with Classic UI. Now you can easily include the same ready-to-use functionality in your project with the modern Flow UI based on Vaadin 24.

### Maps

The **Maps** add-on has undergone a complete overhaul. It now features a new API and excellent support in Studio.

Here is an example that demonstrates how to display OpenStreetMap with a marker at a specific location:

```xml
<maps:geoMap id="map" width="100%" height="100%">  
    <maps:layers>  
        <maps:tile>  
            <maps:osmSource/>  
        </maps:tile>  
        <maps:vector id="pointsLayer">  
            <maps:vectorSource/>  
        </maps:vector>  
    </maps:layers>  
</maps:geoMap>
```

```java
@ViewComponent  
private GeoMap map;

@Subscribe  
public void onInit(InitEvent event) {  
    VectorLayer vectorLayer = map.getLayer("pointsLayer");  
    VectorSource vectorSource = vectorLayer.getSource();  
    vectorSource.addFeature(new MarkerFeature(
            GeometryUtils.createPoint(12.496176, 41.902695)));  
}
```

![maps-1.png]({{strapiUrl}}/uploads/maps_1_4eee2ceb1f.png)

This example is of the "hello world" category and obviously doesn't cover all add-on features. In fact, the map can contain the tile, image and vector layers, each with different data providers. It can display markers, points, polylines and polygons. The work on this add-on is not yet complete, it will be significantly improved in the next release.

### Dynamic Attributes

The **Dynamic Attributes** add-on allows you to define new entity attributes without changing the database schema and restarting the application. Additional attributes defined for an entity can be optionally split into multiple categories. 

For example, a Book entity can be classified into two categories: *Electronic* and *Paper*. The electronic books have *Available Formats* and *File Size* attributes, whereas paper books have *Cover Type*, *Weight* and *Dimensions* attributes. You define dynamic attributes in the application UI:

![dyn-attr-1.png]({{strapiUrl}}/uploads/dyn_attr_1_245703aa5e.png)

After configuring the attributes, users can view and enter them in the existing views:

![dyn-attr-2.png]({{strapiUrl}}/uploads/dyn_attr_2_8104f76ac1.png)

Dynamic attributes are automatically shown either in the special `dynamicAttributesPanel` component (as shown above), or in any existing `formLayout` and `dataGrid`. 

### Notifications

The **Notifications** add-on is designed for sending in-app or email notifications to the users. A notification can be sent though the API or using the view provided by the add-on:

![notifications-2.png]({{strapiUrl}}/uploads/notifications_2_66ea20745f.png)

The application UI should include the `notificationsIndicator` component, for example in the `main-view.xml`:
```xml
<appLayout>  
    <navigationBar>  
        <header ...>
	        ...
            <ntf:notificationsIndicator classNames="ms-auto me-m"/>  
        </header>  
    </navigationBar>
```

The recipients will then be able to see the number of unread notifications in the indicator and open them in the convenient UI:

![notifications-1.png]({{strapiUrl}}/uploads/notifications_1_fd86c7b8d3.png)

### Search

The **Search** add-on provides the integration with Elasticsearch to enable full-text search functionality across data and uploaded files in your application. In order to use the add-on, you only need to follow a few simple steps.

Define the connection to Elasticsearch:
```
jmix.search.elasticsearch.url = http://localhost:9200
```

Create an annotated Java interface describing what has to be indexed:
```java
@JmixEntitySearchIndex(entity = Book.class)  
public interface BookIndexDef {  
  
    @AutoMappedField(includeProperties =  
            {"title", "author", "publisher", "genre.name"})  
    void bookMapping();  
}
```

Add the `searchField` component to the application UI:
```xml
<drawerLayout>  
    <section ...>
		<search:searchField/>
```

That's it. The Book entity data will be automatically indexed (and reindexed on each change) and users will be able to perform full-text queries in the created index:

![search-1.png]({{strapiUrl}}/uploads/search_1_8033d11fb1.png)

The search results are automatically filtered according to the data access permissions of the current user, eliminating any concerns of information leaks.

### WebDAV

The **WebDAV** add-on provides access to files located in the file storage through the WebDAV protocol. This allows users to seamlessly open and edit files using their desktop applications (Word, Excel, LibreOffice, etc.) without the need to download and upload files to the web application. On the UI layer, the add-on provides a specific upload field and the administrative view for managing files and their versions:

![webdav-1.png]({{strapiUrl}}/uploads/webdav_1_6529188771.png)

### Bulk Editor

The **Bulk Editor** add-on is designed to allow users to change attribute values for multiple entity instances at once. It provides an action which you can add to any `dataGrid`:
```xml
<dataGrid id="booksDataGrid" ...>  
    <actions>
	    ...
        <action id="bulkEdit" type="bulked_edit"/>  
    </actions>
```

This action opens a dialog where the user can enter values for entity attributes. These attributes will be updated for all selected entity instances:

![bulk-edit.png]({{strapiUrl}}/uploads/bulk_edit_b1fa690932.png)

### JMX Console

The **JMX Console** add-on provides a web interface to Java Management Extensions (JMX) API. It allows system administrators to inspect JMX beans, edit attributes and invoke operations right in the application UI:

![jmx-console-2.png]({{strapiUrl}}/uploads/jmx_console_2_e9e02b178f.png)
![jmx-console-2.png]({{strapiUrl}}/uploads/jmx_console_2_e9e02b178f.png)

## BPM Improvements

The **DMN table modeler** is now available in the application UI:

![dmn-modeler.png]({{strapiUrl}}/uploads/dmn_modeler_1386f91f7f.png)

The **process form wizard** can now generate fully functional views for editing process variables and choosing outcomes.

The wizard shows variables defined in the process:

![bpm-form-wizard-1.png]({{strapiUrl}}/uploads/bpm_form_wizard_1_a352e3e0d0.png)

and allows you to define outcomes:

![bpm-form-wizard-2.png]({{strapiUrl}}/uploads/bpm_form_wizard_2_25ca0fd84e.png)

Based on your choice, the wizard generates the view code for injecting process variables into UI components and completing the task with the selected outcomes:
```
@ProcessForm(outcomes = {  
        @Outcome(id = "submit"),  
        @Outcome(id = "reject")  
})
// ...
public class BpmProcessForm extends StandardView {  
  
    @Autowired  
    private ProcessFormContext processFormContext;  
  
    @ProcessVariable  
    @ViewComponent    
    private EntityPicker<Book> book;  

	// ...	
    @Subscribe("submitBtn")  
    protected void onSubmitBtnClick(ClickEvent<JmixButton> event) {  
        processFormContext.taskCompletion()  
                .withOutcome("submit")  
                .saveInjectedProcessVariables()  
                .complete();  
        closeWithDefaultAction();  
    }  
```

## Data Grid Improvements

This release includes significant enhancements to the `dataGrid` component which is widely used for presenting data in a tabular format.

Now users can sort `dataGrid` by multiple columns. The sort order is indicated by numbers displayed next to the sorting arrows:

![data-grid-sort-1.png]({{strapiUrl}}/uploads/data_grid_sort_1_cc3d2b2b16.png)

Sorting is defined by the `multiSort`, `multiSortOnShiftClickOnly` and `multiSortPriority` attributes of the `dataGrid` component.

Another new feature is aggregation of values in rows. To configure aggregation for a column, set the `aggregatable` attribute of the `dataGrid` component to true, add the `aggregation` element to the column and select the aggregation type. Aggregated values will be shown in a separate row:

![data-grid-aggregation-1.png]({{strapiUrl}}/uploads/data_grid_aggregation_1_c9d98f2a41.png)

The next improvement is the ability to assign renderers to `dataGrid` columns declaratively. Those who are familiar with Jmix Classic UI will find that columns with declarative renderers closely resemble "generated columns" in Classic UI. You define a column in XML and create a handler method that returns a renderer:
```java
@Supply(to = "stepsDataGrid.completed", subject = "renderer")  
private Renderer<UserStep> stepsDataGridCompletedRenderer() {  
    return new ComponentRenderer<>(userStep -> {
	    // ...
        return checkbox;  
    });  
}    
```

There are several pre-built renderers available that can be assigned to a column in XML in order to format dates and numbers. Additionally, a column can now be defined in XML without being bound to an entity attribute, solely for the purpose of declaring a renderer for it.

And perhaps the most exciting new feature of the data grid is a filter in column headers. You can define which columns should have a filter using the `filterable` attribute of the `column` XML element. Filterable columns have the "funnel" icon in their headers. If the user clicks this icon, a dialog with the property filter condition appears:

![data-grid-filter-1.png]({{strapiUrl}}/uploads/data_grid_filter_1_cdbc1c614c.png)

If a condition is set, the icon in that column is highlighted:

![data-grid-filter-2.png]({{strapiUrl}}/uploads/data_grid_filter_2_3b2b2081d0.png)

The concept of a filter in the column headers is familiar to users from many popular products including Excel, so this feature is easy to discover and use. We believe that this approach to filtering data is an excellent addition to the other two components aimed for the same task: `genericFilter` and `propertyFilter`. The `genericFilter` component is fully customizable at runtime and provides advanced conditions, but may not be the easiest to use. On the other hand, `propertyFilter` is straightforward for users but needs to be configured by the developer beforehand. The data grid column filter is similar to `propertyFilter` in capabilities, but it doesn't occupy any screen space and therefore can be the default choice for most views displaying tables of data.

It's important to note that all three filtering features can be used together on the same view and data loader without any conflicts. The conditions of all filters will simply be combined using the logical AND operator.

## New UI Components and Facets

### VirtualList

The new `virtualList` component is designed for displaying lists of items with arbitrary content. It only renders the portion of items that is currently visible, ensuring good performance regardless of the complexity of the content.

`virtualList` can be used in views instead of `dataGrid`. You define the component in XML and connect it to a collection data container:
```xml
<virtualList id="stepsVirtualList" itemsContainer="stepsDc"/>
```

The filtering and paging components like `genericFilter` and `simplePagination` connected to the data loader will affect the content of `virtualList` the same as of `dataGrid`.

Then you need to create a handler method that renders the list item content:
```java
@Supply(to = "stepsVirtualList", subject = "renderer")  
private Renderer<Step> stepsVirtualListRenderer() {  
    return new ComponentRenderer<>(step -> {
	    // ...
        return hbox;  
    });  
}
```

After spending some effort to coding the layout of the `virtualList` items, you can get a view similar to this one:

![virtual-list-1.png]({{strapiUrl}}/uploads/virtual_list_1_42df36244d.png)

### Html

The `html` component allows you to insert arbitrary HTML content into views. The content can be defined inline in the nested `content` element, in a file located in the project resources, or in the message bundle to be easily internationalized. 

### Settings

The `settings` facet saves and restores settings of visual components for the current user. The facet automatically saves parameters of `dataGrid` columns, `opened` state of `details` and `genericFilter`, a selected page size of `simplePagination`. You can just drop the facet to a view and set its `auto="true"` attribute, and the facet will manage settings of all supported components of the view that have identifiers.

The `settings` facet also provides handlers that allow you to save and restore any properties of the view and its components.

### Timer

The `timer` facet is designed to run some view code at specified time intervals. It works in a thread that handles user interface events and can update view components. To use the facet, define its parameters in XML and create a handler for `TimerActionEvent`:
```xml
<timer id="timer" delay="2000" repeating="true" autostart="true"/>
```

```java
@Subscribe("timer")  
public void onTimerTimerAction(final Timer.TimerActionEvent event) {
	// ...
}
```

## Fetching Items in Dropdowns

This release introduces a new and efficient method for loading data into dropdown components, such as `comboBox`, `entityComboBox` and `multiSelectComboBox`. Now you don't have to define a collection data container for the dropdown items and load it with the full list of options in advance. Instead, you can define the `itemsQuery` nested element in the dropdown component itself and write a query like this:
```xml
<entityComboBox id="departmentField" property="department" pageSize="30">
    <itemsQuery class="com.company.onboarding.entity.Department"
                fetchPlan="_instance_name"
                searchStringFormat="(?i)%${inputString}%">
        <query>
            <![CDATA[select e from Department e 
            where e.name like :searchString order by e.name]]]]><![CDATA[>
        </query>
    </itemsQuery>
</entityComboBox>
```

The query will be executed when the user opens the dropdown and results will be limited to `pageSize` rows (50 by default). When the user scrolls through the list, data will be loaded by pages. If the user enters some text into the field, it is used for filtering the results.

Instead of writing the JPQL query in XML, you can define the `itemsFetchCallback` handler and load data programmatically from any source.

The `itemsQuery` feature offers significantly better performance for large datasets compared to the old approach of using separate collection data containers. With `itemsQuery`, items are loaded in small batches, reducing memory usage, and filtering is performed at the data store level. As a result, you can use datasets of virtually any size as sources of items in dropdown lists.

Obviously, for small datasets, using a separate pre-loaded collection container is still a better choice as it will provide faster response to the user.

## View Designer Improvements

Now, let's discuss the new features and enhancements in Studio.

Probably the most noticeable change in Studio is that the Jmix UI tool window with the hierarchy and properties of components is now displayed in the view controller, allowing for various operations without the need to open the XML descriptor.

It can be very convenient to see the components tree, change component properties or even add new components while working with Java code in the controller.

![view-designer-1.png]({{strapiUrl}}/uploads/view_designer_1_ff44a81c60.png)

There is another improvement related to the **Preview** panel. 

Showing preview requires building the frontend and starting Vaadin Development Mode Server, which can be time-consuming. To save time on the project opening, the **Preview** panel is now opened only when you click **Start Preview** button in the top panel of the XML editor. Once activated, the preview will remain active for all subsequently opened views of the project. To deactivate the preview, simply click **Stop Preview**.

We have also done a lot of work on separating the preview functionality from the rest of the visual designer mechanisms. The preview uses JCEF embedded browser which is sensitive to the nuances of non-standard configuration of the project, IDE, and operating system. Now potential problems in this fragile part of the system don't affect the **Jmix UI** tool window and code generation features.

## Coding Assistance

In this release, we have introduced a brand new approach for injecting dependencies and UI components into view classes and Spring beans.

Once you start typing characters inside a method body, a code completion dropdown will appear, showing the available beans, UI components, local variables, and class fields. Beans and UI components that have not yet been injected into the class will be displayed in italic font. If you select one of these items, it will be automatically injected into the constructor or a field with the appropriate annotation (`@Autowired` or `@ViewComponent`), making it immediately available for use at the current cursor position.

![inject-by-code-completion-1.gif]({{strapiUrl}}/uploads/inject_by_code_completion_1_8ca4625cf4.gif)

With this feature, finding and injecting available beans and UI components is a breeze. We hope you will enjoy it!

## Support for Data Repositories

Studio now has full support for creating and managing Spring Data repositories.

You can create a repository by clicking **New** → **Data Repository** in the **Jmix** tool window toolbar. Studio will create the repository interface and display it under the entity node.

Use the **Add Derived Method** and **Add Query Method** buttons in the actions panel of the repository code editor to create repository methods with derived or explicit queries:

![data-repositories-1.png]({{strapiUrl}}/uploads/data_repositories_1_e3ce862bca.png)

For existing methods of a repository, Studio displays a gutter icon that allows you to adjust the method parameters, for example to add sorting or a fetch plan:

![data-repositories-2.png]({{strapiUrl}}/uploads/data_repositories_2_37f7bd9fdc.png)

## Commenting Data Model

One more feature that I would like to highlight in this article is the ability to add comments to entities and their attributes.

The entity designer now contains the **Comment** fields for both the entity and each attribute. You can set comments and they will be displayed in the fields:

![data-model-comment-1.png]({{strapiUrl}}/uploads/data_model_comment_1_a185ba4ff6.png)

The text entered in the designer is stored in the `@Comment` annotations of the entity class and its fields:
```java
@Comment("""
        Stores information about books.
        Has reference to Genre.""")
@JmixEntity
@Table(name = "BOOK")
@Entity
public class Book {
	// ...
	
	@Comment("Book title")
	@Column(name = "TITLE", nullable = false)  
	private String title;
```

Studio generates `setTableRemarks` and `setColumnRemarks` Liquibase changelog operations to store comments in the database schema (for all databases except HSQL). This allows the comments to be accessed through any database inspection tool. You can also extract comments from metadata or directly from class annotations in order to display them in the application UI or generate documentation.

## What's next?

In the next feature release scheduled for February 2024, we are going to implement the new Charts add-on and finish the work on the Maps add-on features. The UI layer will be enhanced with the addition of the RichTextArea component, horizontal main menu and the ability to search through the main menu items. We are also going to streamline the usage of data repositories in UI views.

On the Studio side, we'll provide hot deployment of BPMN business process definitions, the generation of custom REST controllers, and the scaffolding of integration tests for your entities and views.

Our detailed roadmap for future releases is available as a <a href="https://github.com/orgs/jmix-framework/projects/5" target="_blank">GitHub project</a>. Patches for the current version 2.1 will be released approximately once a month to ensure regular updates.

We appreciate your feedback on our <a href="https://forum.jmix.io" target="_blank">forum</a>, and we are grateful to everyone who has contributed their ideas, suggestions, and bug reports!
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix is recognized as a "High Performer" and ranks among the top 5 Java web frameworks in G2 Grid Reports ]]></title>
            <link>https://www.jmix.io/blog/g2_review_jmix</link>
            <guid>https://www.jmix.io/blog/g2_review_jmix</guid>
            <pubDate>Fri, 03 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/jmix_high_performer_g2_992cc253d0.png">Our latest article showcases Jmix's esteemed recognition as a "High Performer" and position in the G2 Grid Reports for Java web frameworks. Dive in to discover more about this report.]]></description>
            <content:encoded><![CDATA[<a target="_blank" href="https://www.g2.com/products/jmix/reviews">G2</a> is a well-known platform that ranks products and sellers based on a combination of authentic reviews from its vast user community and data aggregated from online sources and social networks. The culmination of these scores is visualized on G2's proprietary Grid®. This invaluable tool assists users in comparing products, simplifying the buying process, and pinpointing the top products grounded in real-world peer experiences. 

It fills us with immense pride to announce that Jmix has not only been recognized but has also earned distinction across several crucial categories on the G2 Grid®. This highlights our commitment and the value we consistently deliver to our customers. 

The rankings are almost too plentiful to name individually – an excellent problem to have – but we’ve assembled a few highlights for you: 

Jmix received this recognition based on several high-value characteristics, including Ease of Use, Language Support, Customer Service, Time-saving Capabilities, and User-friendliness. This reflects our "learning by doing" approach and our focus on user-friendliness and efficient service.

Spotlight Categories: 

- Java Web Frameworks 
- Application Development Platforms 
- Business Process Management Software  

We especially want to highlight our notable position in the G2 Grid® for  <a target="_blank" href="https://www.g2.com/categories/java-web-frameworks#grid">Java Web Frameworks</a>, which further underscores the growing appreciation and trust in Jmix within the developer community. 

<img src="{{strapiUrl}}/uploads/Screenshot_at_Nov_02_17_39_21_a952e0a669.png" width="1448">

G2 Grid® for Java Web Frameworks Highlights: 

**Momentum Score:** G2 Grid® showcases Jmix's outstanding achievements, especially on the "Momentum Score" axis. This is a proof of our company's rapid growth and fast adoption rate in the developer and entrepreneur communities. 

**User Satisfaction:** Our  placement emphasizes high ratings and positive feedback from our diverse users. 

**Quest for the Pinnacle:** We have set our eyes on the coveted upper right quadrant - the area of "Momentum Leaders". Backed by the continued support of our active community, we are optimistic about the milestones ahead. 

Also this season, the Jmix team is happy to have been awarded the "High Performer" badge on G2.  An average rating of 4.8 out of 5 based on G2 reviews demonstrates our commitment to unrivaled support and positively impacting our customer base. 

Discover firsthand accounts of Jmix experiences or share your unique journey with Jmix on <a target="_blank" href="https://www.g2.com/products/jmix/reviews">G2</a>'s review platform. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: Single Business process automation tool for Business analysts and Java Developers]]></title>
            <link>https://www.jmix.io/blog/bpm-tool</link>
            <guid>https://www.jmix.io/blog/bpm-tool</guid>
            <pubDate>Mon, 25 Sep 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/1640e856_68b3e7acab.png">In this webinar, we showcase Jmix's runtime and scalability advantages, enabling developers to optimize BPM solutions with ease. ]]></description>
            <content:encoded><![CDATA[In this webinar, we showcase Jmix's runtime and scalability advantages, enabling developers to optimize BPM solutions with ease. Through live coding examples and real-world scenarios, you'll witness firsthand how Jmix revolutionizes the way analysts and developers work together, enabling them to build easily efficient and scalable BPM solutions using familiar tools for each role and establish a seamless design process.
You can see recording of webinar on <a href="https://www.youtube.com/live/6IOLG8E7ueI?si=O9zVifdAgaeqm_Cl" target="_blank">our youtube channel</a>

<youtube data-video-id="6IOLG8E7ueI"></youtube>

## The topics on webinar agenda:

+ <time-code data-time="0:05"> Introduction
+ <time-code data-time="2:05"> What is Jmix and why should you care?
+ <time-code data-time="3:12"> What does data-model design give to BPM?
+ <time-code data-time="3:58"> What does process-driven logic give to OLTP?
+ <time-code data-time="4:37"> Pros and Cons for IDE-based BPMS
+ <time-code data-time="7:02"> Our motto - Find the right tool for your task
+ <time-code data-time="7:57"> Business analysts and Developers/System analysts mindset troubles
+ <time-code data-time="10:11"> BPM workflow: how Business analysts communicate with Developers (PLC/SDLC)
+ <time-code data-time="11:12"> Gradual ERP + BPM Creation project use case
+ <time-code data-time="12:25"> Use cases
+ <time-code data-time="13:23"> What users hate about BPMS/Low-Code Platforms?
+ <time-code data-time="14:54"> Whom do we target?
+ <time-code data-time="15:47"> Demo use case description: Development BPM open source solution
+ <time-code data-time="16:13"> Live Coding Session
+ <time-code data-time="1:16:08"> Key takeaways
+ <time-code data-time="1:17:41"> What to do next?





<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How Jmix integrates bpmn-js to boost process centric application development]]></title>
            <link>https://www.jmix.io/blog/how-jmix-uses-bpmn-js</link>
            <guid>https://www.jmix.io/blog/how-jmix-uses-bpmn-js</guid>
            <pubDate>Thu, 10 Aug 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/bpm_jmix_d7aa458416.png">Check out the latest article in BPMN.io project to discover how developers can design BPMN models and connect business logic seamlessly without the need to switch between different tools, all within the IntelliJ IDEA environment.]]></description>
            <content:encoded><![CDATA[&nbsp;]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: What's new in Jmix 2.0]]></title>
            <link>https://www.jmix.io/blog/webinar-jmix2-release</link>
            <guid>https://www.jmix.io/blog/webinar-jmix2-release</guid>
            <pubDate>Thu, 27 Jul 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_2_0_FB_1200x630_87bc397f06.png">In this webinar, we talked about new features and improvements in Jmix framework and Studio 2.0. ]]></description>
            <content:encoded><![CDATA[In this webinar, we talked about new features and improvements in Jmix framework and Studio 1.5. We also took a closer look at the new features and discussed future plans.  You can see recording of webinar on <a href="https://www.youtube.com/live/drthU9RJwyM?feature=share&t=60" target="_blank">our youtube channel</a>

<youtube data-video-id="drthU9RJwyM"></youtube>

## The topics on webinar agenda:

+ <time-code data-time="1:41"> Introduction
+ <time-code data-time="2:12"> Updated technology stack
+ <time-code data-time="8:49"> Flow UI as the main and only UI technology
+ <time-code data-time="11:42"> Studio improvements
+ <time-code data-time="18:03"> Quick cloud deployment
+ <time-code data-time="24:59"> Authentification in Generic REST
+ <time-code data-time="32:58"> Plans for Future releases
+ <time-code data-time="35:00"> Q&A




<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 2.0 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-2-0-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-2-0-is-released</guid>
            <pubDate>Wed, 12 Jul 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/2_0_71096369cb.png">Overview of the new features and important changes of the Jmix 2.0 feature release.]]></description>
            <content:encoded><![CDATA[Jmix 2.0 is a major milestone in the evolution of the product. This release introduces a number of important features and brings about significant changes to the Jmix landscape. In this blog post, we highlight the updates and discuss their implications for your application projects.

For full details and upgrade instructions, make sure to visit the <a target="_blank" href="https://docs.jmix.io/jmix/2.0/whats-new/index.html">What's New</a> page in the documentation.

## Updated Technology Stack

Obviously the most impactful change in Jmix 2.0 is the new technology stack. The runtime part now depends on the latest versions of the foundational frameworks:
- Spring Boot 3.1, Spring Framework 6.0, Spring Security 6.1 in Jmix core
- Vaadin 24.0 in Flow UI subsystem
- EclipseLink 4.0 as JPA implementation in data access
- Flowable 7.0 as BPM engine

The new versions of base libraries have a sufficient support period ahead which guarantees a steady development of Jmix framework and applications. But the other side of the coin is that now you need at least JDK 17 to build and run your applications, and if you deploy in WAR, you need to update your Tomcat application server to version 10.

Also, the Classic UI subsystem is not included in Jmix 2.0 due to the incompatibility between Vaadin 8 used in Classic UI and the new Jakarta Servlet API and Spring 6. So to upgrade from Jmix 1.5 Classic UI to Jmix 2.0 you need to replace the UI layer. For more information about possible options, please refer to our previous blog post: <a target="_blank" href="https://www.jmix.io/blog/extended-support-for-classic-ui/">Extended Support for Classic UI</a>.

The new Studio 2.0 provides smooth migration for Jmix 1.5 applications with Flow UI. 

## Flow UI for Add-ons

We've implemented Flow UI for BPM, Business Calendars, Email and Reports add-ons, so you can use them now with Jmix 2.0.

The BPM add-on now has fully-functional runtime BPMN modeler and administration UI:

<img src="{{strapiUrl}}/uploads/Pasted_image_20230706184755_9f7b8a80d8.png" width="1437">

The new UI of the Business Calendars add-on:

<img src="{{strapiUrl}}/uploads/Pasted_image_20230706185401_d73e4ce183.png" width="1448">

The Email history view:

<img src="{{strapiUrl}}/uploads/Pasted_image_20230706190205_52329d5ec6.png" width="1448">

The report designer is now much cleaner and usable on low resolution screens:

<img src="{{strapiUrl}}/uploads/Pasted_image_20230706190654_decd78543e.png" width="1471">

To simplify the UI for most cases, the report designer assumes that a band has a single dataset. But if you select the *Multiple Datasets* checkbox, the designer will switch to a more complex view:

<img src="{{strapiUrl}}/uploads/Pasted_image_20230706191624_cc938fd4d6.png" width="818">

## GenericFilter Component

The `genericFilter` component is now fully-functional and enables you to create configurations and custom conditions both during design time and runtime. The runtime configurations and custom conditions can be managed by end users:

<img src="{{strapiUrl}}/uploads/Pasted_image_20230706193806_f15859efc6.png" width="1260">

## CodeEditor Component

The new `codeEditor` component based on Ace editor enables users to view and edit code with syntax highlighting, as well as other advanced features such as different color themes:

<img src="{{strapiUrl}}/uploads/Pasted_image_20230706194153_a926065a28.png" width="1121">

And the same as many other Jmix UI components, it can be easily bound to your data model to edit code stored in an entity attribute.

## Preventing Browser Tab Closing

A frequent problem in web applications is loss of entered data when a user accidentally closes the browser tab. Now, when an entity detail view is displayed, the browser shows a standard confirmation about leaving the page if the user attempts to close the browser tab:
<img src="{{strapiUrl}}/uploads/Pasted_image_20230707113855_4f421a965f.png" width="372">

You can use the `setPreventBrowserTabClosing()` method to turn on or off this behaviour in any view.

## Quick Cloud Deployment

Developers often need to demonstrate their application to users, management or colleagues. It's easy if you can do it directly on your local computer or if you have a CI/CD pipeline deploying your code to a demo or test environment. But if you are a solo developer and you need to showcase your application to people on the other side of the world, the best option is to deploy it to the cloud.

Studio now allows you to do this in a few simple steps that don't require any specific knowledge about deployment or clouds:
- Register an account on AWS
- Install Docker on your local computer
- Go through a few steps of the Quick Cloud Deployment wizard in Studio. 

As a result, within minutes, your application will be up and running on an AWS EC2 server, accessible to users worldwide.

Behind the scenes, Studio generates a `docker-compose.yaml` for your application, creates an EC2 instance through the AWS API, installs Docker on it, builds an application image on the server, and runs `docker-compose` with your application and PostgreSQL database containers. The database and file storage data are mapped to the server file system, ensuring that all data is preserved when you change the source code, rebuild, and redeploy the application.

This feature was considered unfinished and hidden in Studio for a long time, now in v.2.0 it's finally ready to use.

## Studio UI/UX Improvements

The **Jmix** tool window now displays a section with all Spring beans defined in the project:
<img src="{{strapiUrl}}/uploads/Pasted_image_20230707163923_79c52cf9a5.png" width="567">

You can also group the beans and other elements by packages using this option:
<img src="{{strapiUrl}}/uploads/Pasted_image_20230707164114_4b458c7e3e.png" width="645">

The **Beans** section displays only beans defined by the `@Component` or `@Service` annotation on the bean class. Beans created in Java configurations using the `@Bean` annotations are not shown here.

The **Inject** dialog now displays all beans defined in the entire project classpath, including the ones defined in Java configurations with `@Bean` annotations. The `Other Beans` section have smart grouping to simplify discovering of available beans:
You can also group the beans and other elements by packages using this option:
<img src="{{strapiUrl}}/uploads/Pasted_image_20230707183411_1707f60e1e.png" width="856">

There was a topic on our forum, where the user complained that Studio generates code which immediately produces warnings from IntelliJ like "_something_ can have 'final' modifier". We thought that it was a fair point and Studio should comply with the default set of IDE inspections. As a result, all generated code now includes the recommended final modifiers. If you don't like it, you can adjust the Jmix plugin settings and disable this option on the **Project Settings** tab.

Another improvement that affects generated code is that now `OffsetDateTime` type is used for timestamps in `Audit of creation`, `Audit of modification` and `Soft Delete` traits. So the database will store the timestamps with timezone.

## BPM in Studio

If your project includes the <a target="_blank" href="https://docs.jmix.io/jmix/bpm/index.html">BPM add-on</a>, the **Jmix** tool window now has the `BPM` section. The section displays BPMN processes, process drafts and DMN tables:

<img src="{{strapiUrl}}/uploads/Pasted_image_20230707190821_212630f49d.png" width="883">

You can copy process definitions between the **Process Drafts** and **Processes** folders using the action buttons at the top of the modeler window. This allows you to organize a simple workflow: you work on the process definition in the **Process Drafts** folder, and copy it to **Processes** as soon as it's ready. All process definitions located in the **Processes** folder will be deployed at the next application start. If something goes wrong with the deployment, you can copy the process back to drafts and remove it from **Processes** to let the application start.

## Authentication in Generic REST

In release 1.4, we introduced the Jmix Authorization Server as a preview feature. In 2.0, it became the main way of authentication in Generic REST. The motivation for this change is twofold. On one hand, the old Jmix Security OAuth2 module cannot be used in Jmix 2.0 because it depends on outdated Spring Security OAuth, which is incompatible with Spring Boot 3. On the other hand, we should follow best practices and get rid of deprecated OAuth password grant flow.  

Now if you are using Generic REST add-on, you have to choose the grant type, which determines how the REST clients will obtain access tokens. Jmix Authorization server supports two grant types: Client Credentials and Authorization Code. They both have an advantage over the Password grant in that they don't allow the client application to collect or possess the user password.

The most similar to the old Password grant and easiest to implement is the Client Credentials grant. It should be used for server-to-server communication, such as integration with a third-party system. In this case, the configuration of Jmix Authorization server includes the association between the client and the list of existing application roles, e.g.  `rest-minimal`, `order-management`, etc. To obtain the access token, the client just needs to pass its `client-id` and `client-secret` in the basic authentication header. Subsequent API calls with this token will have the security context of a special user with the username equal to `client-id` and the list of roles configured for this client in the application properties. In other words, the client receives the static set of permissions and never operates as a real application user.

The Authorization Code grant is more complicated but it allows the client to work on behalf of the real application user. With this grant type, when the client requests authentication, the Jmix Authorization Server itself shows a login page for the user to enter their username and password. Then, it returns an intermediate authorization code to the client. The client exchanges the code for the access token and uses the token for API calls. Thus, the client operates as a user without ever knowing the user's password.

## Conclusion

With the introduction of the fresh technology stack and production-ready Flow UI, the Jmix platform completes the modernization phase and moves on to steady development. Our team will continue working on implementing new features and constantly improving the overall quality of the product.

In the next feature release scheduled for October 2023, we have planned several important updates. This includes the implementation of Flow UI for several more add-ons, the addition of SuggestionField and SettingsFacet to Flow UI, and improvements in support for data repositories. Our detailed roadmap for the future releases is published as a <a target="_blank" href="https://github.com/orgs/jmix-framework/projects/5">GitHub project</a>.

We welcome your feedback on our forum, and thanks to all who contributed with their ideas, suggestions and bugreports!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How Jmix integrates bpmn-js to boost process centric application development]]></title>
            <link>https://www.jmix.io/blog/test-banner</link>
            <guid>https://www.jmix.io/blog/test-banner</guid>
            <pubDate>Sat, 03 Jun 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/orionthemes_placeholder_image_1_4ca7f527f2.png">Jmix is an open-source high-productivity platform for building enterprise-grade applications.]]></description>
            <content:encoded><![CDATA[Once an enterprise application is released into production, it begins a life of its own. Quite often, implemented functionality is used differently from how it was originally designed—or not used at all. Business users tend to view the system from a different perspective, discovering their own paths and workarounds that can sometimes surprise the development team. 

Beyond questions of how features are used, an even more fundamental concern often arises: are users using the system at all? And if they are, what does “active usage” look like at an enterprise scale? 

<div class="purple-box">
  For example, you may want to understand how actively users are collaborating while working on a project, or how consistently the sales department is entering data that will later be used for analysis.
</div>
<style>
  .purple-box {
    background: #F5F5FD;
    border: 1px solid #342A98;
    border-radius: 16px;
    padding: 15px;
    margin: 20px 0;
  }
</style>

Depending on the business case, insights like these can support strategic decisions about further investment in the system. In this article, however, we will focus on the technical side of the problem and explore active user monitoring and how it can be implemented with Jmix. 

## Metrics for Active Users 

The metrics commonly used in enterprise applications to monitor user activity are largely the same as those used in the retail domain: 

**DAU (Daily Active Users)**– the number of unique users who engage with the system within a 24-hour window. This window works well in enterprise environments too, especially for multinational organisations with distributed teams and flexible working hours. 

**WAU (Weekly Active Users)**– the number of unique users who engage with the system during a week. 

**MAU (Monthly Active Users)** – the number of unique users who engage with the system during a month. 

It is important to note that WAU is not the sum of DAU values over a week, as each user is counted only once within the given period. The same applies to MAU: it is not equal to the sum of DAU or WAU values within a month. 

In addition to these metrics, there is a derived indicator known as **stickiness.** It is calculated as the ratio of the average number of daily active users to the number of weekly or monthly active users. 

![]({{strapiUrl}}/uploads/mau1_436e8c39e1.png)

Stickiness indicates how frequently end users engage with the system. A stickiness value of 100% means that the same users are active every day, which is typically a very positive sign. At the same time, weekly or monthly stickiness can decrease even if the average number of daily active users remains stable, revealing that different users are accessing the system on different days. 

<div class="purple-box">
For example, if developers are expected to fill in timesheets on a daily basis, stickiness metrics can clearly show how consistently this requirement is being followed. 
</div>

The calculations above can be adjusted to better reflect specific business scenarios: 
- **Experiment with averaging methods.** Try both the arithmetic mean and the median to account for strong deviations or skewed distributions. 
- **Refine the definition of an “active user”.** Clearly define which actions contribute to activity, such as viewing or editing documents, generating reports, tracking time, or even the number of clicks. 
- **Consider the working calendar.** While a 24-hour window is suitable for DAU, the number of working days in a week or month still affects WAU and MAU. In Jmix applications, this can be addressed using the Jmix Business Calendar, which supports working shifts, public holidays, and weekends. 

As you might expect, all these metrics can be applied not only to the system as a whole, but also to specific features or functional areas.  

## Collecting metrics with Jmix 

Let’s assume that, after proper business analysis, we have identified which system actions should be tracked. The next step is the technical implementation of business metrics such as DAU, WAU, MAU, and the corresponding stickiness indicators. How can Jmix help with this? 

In Jmix, application metrics are collected, exposed, and exported using the **Micrometer** library. Micrometer is part of Jmix’s observability and monitoring support and is the de facto metrics facade in the Java and Spring ecosystem. In practice, it provides a standard, vendor-neutral way to turn low-level application metrics into meaningful business insights. 

Jmix integrates Micrometer on top of **Spring Boot Actuator**, a Spring Boot module that offers production-ready features for monitoring and managing applications at runtime. This integration provides several benefits: 
- Automatic metrics for core Jmix components 
- Simple configuration through application.properties 
- Compatibility with Spring Boot’s built-in monitoring endpoints and metrics 
- Flexible configuring with the standard Spring mechanisms 

Out of the box, Jmix includes built-in metrics for its main structural units—**Views** and **Data Loaders**. This means that when you create screens and implement data-handling logic, you automatically gain the ability to monitor their behaviour without additional configuration. 

Supported lifecycle stages for **Views** include: 
Create, Load, Init, Before Show, Ready, Inject, Before Close, After Close. 

Supported lifecycle stages for **Data Loaders** include: 
Pre-load, Load, Post-load. 

Additional metrics can be introduced as needed by using the Micrometer API directly, for example by incrementing counters within event listeners that correspond to specific user actions. 

We plan to publish more technical articles that provide step-by-step guidance on configuring application metrics and the supporting monitoring infrastructure. In the meantime, you can explore the example below and consult the [Jmix AI Assistant](https://ai-assistant.jmix.io/), which is always ready to help with technical questions. 

## Metrics visualization  

Once application metrics are available, they can be exposed to monitoring tools immediately. While it is possible to build internal monitoring dashboards in Jmix using the [Charts add-on](https://www.jmix.io/marketplace/charts/), the more common approach is to rely on established observability tooling. 

A typical setup uses **Prometheus** for external metric collection and storage, and **Grafana** for visualisation. Both tools integrate seamlessly with Micrometer through Spring Boot Actuator, making them a natural choice for production environments. 

Jmix also provides ready-made [Grafana dashboards for Jmix](https://github.com/jmix-framework/jmix-grafana-dashboards) specifically designed for visualising application metrics. As a result, there is usually no need to introduce custom visualisation logic into the application itself. Instead, you can rely on existing infrastructure and well-established practices to analyse statistical and performance data. 

As mentioned earlier, **Views** and **Data Loaders** are available for monitoring out of the box. In Prometheus, these metrics are exposed using the following prefixes: 

- 'jmix_ui_views' — supported tags: 'lifeCycle', 'view' 
- 'jmix_ui_data' — supported tags: 'lifeCycle', 'view', 'dataLoader' 

These metrics can be used directly in Prometheus queries and Grafana dashboards to gain detailed insights into user interaction patterns and application behaviour. For example: 

```
jmix_ui_data_seconds_max{dataLoader="usersDl",lifeCycle="load",view="User.list",} 0.005668899 
```


## Metrics implementation for Active User Monitoring 

Now let’s return to the business metrics introduced at the beginning of this article. To demonstrate how they can be implemented in practice, we have prepared a [sample application](https://github.com/jmix-projects/jmix-app-usage-metrics-sample/) whose purpose is to register active users and calculate the corresponding metrics for Prometheus. 

<div class="blog-demo-banner banner-wrapper">
  <div class="container" style="padding: 0;">
    <div class="main-banner reverse">
      <div class="banner-devops-cloud__parallax" ref="decorations">
    <div class="parallax-decorations__decorate _decorate-3" data-depth="0.1">
      <div class="parallax-decorations__figure"></div>
    </div>
    <div class="parallax-decorations__decorate _decorate-4" data-depth="-0.06">
      <div class="parallax-decorations__figure"></div>
    </div>
    <div class="parallax-decorations__decorate _decorate-5" data-depth="-0.08">
      <div class="parallax-decorations__figure"></div>
    </div>
    <div class="parallax-decorations__decorate _decorate-6" data-depth="-0.07">
      <div class="parallax-decorations__figure"></div>
    </div>
    <div class="parallax-decorations__decorate _decorate-7" data-depth="-0.08">
      <div class="parallax-decorations__figure"></div>
    </div>
    <div class="parallax-decorations__decorate _decorate-8" data-depth="-0.09">
      <div class="parallax-decorations__figure"></div>
    </div>
    <div class="parallax-decorations__decorate _decorate-9" data-depth="0.1">
      <div class="parallax-decorations__figure"></div>
    </div>
      </div>
     <div class="main-banner__wrapper">
        <div class="main-banner__cols">
          <div class="main-banner__col _right">
            <div class="main-banner__content">
              <h2 class="title main-banner__title ">Explore Jmix in a custom demo <br/>with platform experts</h2>
              <div class="main-banner__img _mobile">
                <img src="{{strapiUrl}}/uploads/Clip_path_group_10_881ed5ae20.png" alt="telegram banner mobile image"
                  loading="lazy" />
              </div>
              <div class="main-banner__btn">
                <a href="/schedule-a-demo/" class="btn arrow fill-red">
                  Book a Demo
                  <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" class="arrow-icon">
                    <path fill-rule="evenodd" clip-rule="evenodd"
                      d="M1 8C1 7.44772 1.44772 7 2 7H14C14.5523 7 15 7.44772 15 8C15 8.55228 14.5523 9 14 9H2C1.44772 9 1 8.55228 1 8Z" />
                    <path fill-rule="evenodd" clip-rule="evenodd"
                      d="M8.29301 2.29288C8.68354 1.90236 9.31671 1.90238 9.70722 2.29291L14.707 7.29291C15.0975 7.68343 15.0975 8.31658 14.707 8.7071L9.70711 13.7071C9.31659 14.0976 8.68343 14.0976 8.2929 13.7071C7.90237 13.3166 7.90237 12.6834 8.29289 12.2929L12.5857 7.99999L8.29298 3.70709C7.90246 3.31656 7.90248 2.68339 8.29301 2.29288Z" />
                  </svg>
                </a>
              </div>
            </div>
          </div>
          <div class="main-banner__col _left">
            <div class="main-banner__img _desctop">
              <img src="{{strapiUrl}}/uploads/Clip_path_group_6_68132cbc3d.png " alt="telegram banner mobile image" />
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>


Alongside the application source code, you will find several useful artefacts: 
- A **README** file that provides a detailed explanation of the implementation 
- Step-by-step instructions showing how to integrate these metrics into your own project 
- A ready-to-import **Grafana dashboard**, as well as a docker-compose file for quickly setting up the monitoring infrastructure 

For the sake of simplicity, this example assumes that a user is considered active as soon as they successfully log in to the system. To implement this logic, we rely on two Jmix add-ons: **Quartz** and **Jmix Business Calendar**. 

Our intermediate goal is to teach the application to expose metrics in the following format: 


```
#HELP active_users_dau The daily active users metric 
#TYPE active_users_dau gauge 
active_users_dau{application="business-metrics-app"} 2.0 
#HELP active_users_mau The monthly active users metrics 
#TYPE active_users_mau gauge 
active_users_mau{application="business-metrics-app", subtype="avg_dau"} 0.42105263471603394 active_users_mau{application="business-metrics-app", subtype="days_count"} 19.0 active_users_mau{application="business-metrics-app", subtype="main_value"} 4.0 
#HELP active_users_wau The weekly active users metrics 
#TYPE active_users_wau gauge 
active_users_wau{application="business-metrics-app", subtype="avg_dau"} 1.600000023841858 active_users_wau{application="business-metrics-app", subtype="days_count"} 5.0 active_users_wau{application="business-metrics-app", subtype="main_value"} 4.0 
```

<div class="blog-roi-banner banner-wrapper">
  <div class="container" style="padding: 0;">
    <div class="main-banner reverse">
      <div class="main-banner__wrapper">
        <div class="main-banner__cols">
          <div class="main-banner__col _right">
            <div class="main-banner__content">
              <h2 class="title main-banner__title white">Estimate business outcomes <br class="desktop" />with the ROI Calculator</h2>
              <div class="main-banner__img _mobile main-banner__img-front">
                <img src="{{strapiUrl}}/uploads/Clip_path_group_13_9b967c1c13.png" alt="telegram banner mobile image"
                  loading="lazy" />
              </div>
              <div class="main-banner__img _mobile main-banner__img-back">
                <img src="{{strapiUrl}}/uploads/Clip_path_group_16_4fa685025d.png" alt="telegram banner mobile image"
                  loading="lazy" />
              </div>
              <div class="main-banner__btn">
                <a href="https://t.me/jmixplatform" target="_blank" class="btn arrow white">
                 Calculate ROI
                  <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" class="arrow-icon">
                    <path fill-rule="evenodd" clip-rule="evenodd"
                      d="M1 8C1 7.44772 1.44772 7 2 7H14C14.5523 7 15 7.44772 15 8C15 8.55228 14.5523 9 14 9H2C1.44772 9 1 8.55228 1 8Z" />
                    <path fill-rule="evenodd" clip-rule="evenodd"
                      d="M8.29301 2.29288C8.68354 1.90236 9.31671 1.90238 9.70722 2.29291L14.707 7.29291C15.0975 7.68343 15.0975 8.31658 14.707 8.7071L9.70711 13.7071C9.31659 14.0976 8.68343 14.0976 8.2929 13.7071C7.90237 13.3166 7.90237 12.6834 8.29289 12.2929L12.5857 7.99999L8.29298 3.70709C7.90246 3.31656 7.90248 2.68339 8.29301 2.29288Z" />
                  </svg>
                </a>
              </div>
            </div>
          </div>
          <div class="main-banner__col _left">
            <div class="main-banner__img _desctop">
              <img src="{{strapiUrl}}/uploads/Clip_path_group_5_70f20d5fa4.png" alt="telegram banner mobile image" />
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>



As shown above, the exported metrics include: 
- DAU, WAU, and MAU values 
- Average DAU (metrics labelled subtype="avg_dau") 
- The number of actual working days in the period (metrics labelled subtype="days_count") 

As you may know,[ PromQL](https://grafana.com/blog/introduction-to-promql-the-prometheus-query-language/) is the primary query language used to retrieve and manipulate data for visualisations in Grafana. However, despite the apparent simplicity of the task, PromQL alone is not sufficient in this case for several reasons: 

- The active_users_dau metric is not a regular gauge. We are not interested in how DAU changes throughout the day; only the final daily value matters. 
- Time data must be properly formatted and aligned to allow aggregation by day. 
- Displaying active_users_wau, active_users_mau, average DAU, and stickiness on the same chart is not straightforward using PromQL alone. 

<div class="blog-youtube-banner banner-wrapper">
  <div class="container" style="padding: 0;">
    <div class="main-banner reverse">
      <div class="main-banner__wrapper">
        <div class="main-banner__cols">
          <div class="main-banner__col _right">
            <div class="main-banner__content">
              <h2 class="title main-banner__title white">Watch Jmix videos on architecture, <br/>practical tutorials and real projects </h2>
              <div class="main-banner__img _mobile main-banner__img-front">
                <img src="{{strapiUrl}}/uploads/Clip_path_group_15_c1522f6293.png" alt="telegram banner mobile image"
                  loading="lazy" />
              </div>
              <div class="main-banner__img _mobile main-banner__img-back">
                <img src="{{strapiUrl}}/uploads/Clip_path_group_14_361705cb41.png" alt="telegram banner mobile image"
                  loading="lazy" />
              </div>
              <div class="main-banner__btn">
                <a href="https://t.me/jmixplatform" target="_blank" class="btn arrow white">
                  Subscribe on YouTube
                  <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" class="arrow-icon">
                    <path fill-rule="evenodd" clip-rule="evenodd"
                      d="M1 8C1 7.44772 1.44772 7 2 7H14C14.5523 7 15 7.44772 15 8C15 8.55228 14.5523 9 14 9H2C1.44772 9 1 8.55228 1 8Z" />
                    <path fill-rule="evenodd" clip-rule="evenodd"
                      d="M8.29301 2.29288C8.68354 1.90236 9.31671 1.90238 9.70722 2.29291L14.707 7.29291C15.0975 7.68343 15.0975 8.31658 14.707 8.7071L9.70711 13.7071C9.31659 14.0976 8.68343 14.0976 8.2929 13.7071C7.90237 13.3166 7.90237 12.6834 8.29289 12.2929L12.5857 7.99999L8.29298 3.70709C7.90246 3.31656 7.90248 2.68339 8.29301 2.29288Z" />
                  </svg>
                </a>
              </div>
            </div>
          </div>
          <div class="main-banner__col _left">
            <div class="main-banner__img _desctop">
              <img src="{{strapiUrl}}/uploads/Clip_path_group_4_c20bf12ed8.png" alt="telegram banner mobile image" />
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>


In our example, these challenges are addressed using Grafana’s powerful [Transformations mechanism](https://grafana.com/blog/you-should-know-about-transformations-in-grafana/). Transformations allow data to be reshaped into a form that best suits a specific visualisation without modifying the original data in the data source and without impacting the data source performance. This significantly extends the practical capabilities of PromQL and enables more advanced dashboards with minimal additional complexity. 

<div class="blog-linkedid-banner banner-wrapper">
  <div class="container" style="padding: 0;">
    <div class="main-banner reverse">
      <div class="main-banner__wrapper">
        <div class="main-banner__cols">
          <div class="main-banner__col _right">
            <div class="main-banner__content">
              <h2 class="title main-banner__title white">Follow Jmix on LinkedIn </h2>
              <div class="blog-linkedid-banner__subtitle">for product updates and expert insights</div>
              <div class="main-banner__img _mobile">
                <img src="{{strapiUrl}}/uploads/Clip_path_group_2_1_78f9b822a6.png" alt="telegram banner mobile image"
                  loading="lazy" />
              </div>
              <div class="main-banner__btn">
                <a href="https://t.me/jmixplatform" target="_blank" class="btn arrow white">
                  Follow on LinkedIn
                  <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" class="arrow-icon">
                    <path fill-rule="evenodd" clip-rule="evenodd"
                      d="M1 8C1 7.44772 1.44772 7 2 7H14C14.5523 7 15 7.44772 15 8C15 8.55228 14.5523 9 14 9H2C1.44772 9 1 8.55228 1 8Z" />
                    <path fill-rule="evenodd" clip-rule="evenodd"
                      d="M8.29301 2.29288C8.68354 1.90236 9.31671 1.90238 9.70722 2.29291L14.707 7.29291C15.0975 7.68343 15.0975 8.31658 14.707 8.7071L9.70711 13.7071C9.31659 14.0976 8.68343 14.0976 8.2929 13.7071C7.90237 13.3166 7.90237 12.6834 8.29289 12.2929L12.5857 7.99999L8.29298 3.70709C7.90246 3.31656 7.90248 2.68339 8.29301 2.29288Z" />
                  </svg>
                </a>
              </div>
            </div>
          </div>
          <div class="main-banner__col _left">
            <div class="main-banner__img _desctop">
              <img src="{{strapiUrl}}/uploads/Clip_path_group_1_658ef4269c.png " alt="telegram banner mobile image" />
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

## Result 

In summary, we implemented a practical and flexible approach to analysing enterprise application usage, combining configurable working calendars with the powerful visualisation capabilities of Grafana. 

By building on standard monitoring tools such as Prometheus and Grafana, we achieved an effective solution for tracking usage efficiency in Jmix-based applications without adding unnecessary complexity. 

**Key benefits:** 
- **Business-relevant metrics** such as DAU, WAU, MAU, and stickiness derived from real user activity 
- **Flexible calendar awareness**, including working days, holidays, and shifts 
- **Minimal application overhead** by relying on Micrometer, Prometheus, and Grafana 
- **Rich visualisation and analysis** using ready-made dashboards and Grafana transformations 
- **Scalable and extensible architecture** based on industry-standard tooling 

This approach provides a solid foundation for understanding how enterprise systems are actually used and for making informed technical and business decisions.   

<div class="blog-build-banner banner-wrapper">
  <div class="container" style="padding: 0;">
    <div class="main-banner reverse">
      <div class="main-banner__wrapper">
        <div class="main-banner__cols">
          <div class="main-banner__col _right">
            <div class="main-banner__content">
              <h2 class="title main-banner__title white">Build enterprise Java<br/>web applications<br class="mobile"/> faster <span class="mobile">with open-<br/>source tools and AI</span></h2>
              <div class="blog-build-banner__subtitle">with open-source tools and AI</div>
              <div class="main-banner__img _mobile main-banner__img-front">
                <img src="{{strapiUrl}}/uploads/Clip_path_group_12_db7cf92a97.png" alt="telegram banner mobile image"
                  loading="lazy" />
              </div>
              <div class="main-banner__img _mobile main-banner__img-back">
                <img src="{{strapiUrl}}/uploads/Clip_path_group_18_0d94f54e1b.png" alt="telegram banner mobile image"
                  loading="lazy" />
              </div>
              <div class="main-banner__btn">
                <a href="https://t.me/jmixplatform" target="_blank" class="btn arrow white">
                  Build Your App
                  <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" class="arrow-icon">
                    <path fill-rule="evenodd" clip-rule="evenodd"
                      d="M1 8C1 7.44772 1.44772 7 2 7H14C14.5523 7 15 7.44772 15 8C15 8.55228 14.5523 9 14 9H2C1.44772 9 1 8.55228 1 8Z" />
                    <path fill-rule="evenodd" clip-rule="evenodd"
                      d="M8.29301 2.29288C8.68354 1.90236 9.31671 1.90238 9.70722 2.29291L14.707 7.29291C15.0975 7.68343 15.0975 8.31658 14.707 8.7071L9.70711 13.7071C9.31659 14.0976 8.68343 14.0976 8.2929 13.7071C7.90237 13.3166 7.90237 12.6834 8.29289 12.2929L12.5857 7.99999L8.29298 3.70709C7.90246 3.31656 7.90248 2.68339 8.29301 2.29288Z" />
                  </svg>
                </a>
              </div>
            </div>
          </div>
          <div class="main-banner__col _left">
            <div class="main-banner__img _desctop">
              <img src="{{strapiUrl}}/uploads/Clip_path_group_3_ea2e3b8ec7.png " alt="telegram banner mobile image" />
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

![]({{strapiUrl}}/uploads/mau2_324440bc52.png)
 ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Extended Support for Classic UI]]></title>
            <link>https://www.jmix.io/blog/extended-support-for-classic-ui</link>
            <guid>https://www.jmix.io/blog/extended-support-for-classic-ui</guid>
            <pubDate>Thu, 25 May 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Extended_Support_for_Classic_UI_thumbnail_169ab97ab6.jpg">Despite the upcoming release 2.0 with fully-fledged Flow UI, Jmix remains committed to supporting Classic UI projects with continued updates in the 1.x branch.]]></description>
            <content:encoded><![CDATA[The upcoming Jmix release 2.0, which is scheduled for June 2023, will be based on the newest versions of the base frameworks: Spring Boot 3, Spring 6, EclipseLink 4. The upgrade of the technology stack won’t bring many new features to application developers, but it is needed to provide supported versions of underlying libraries. The lifecycle of library versions used in Jmix 1.x is coming to an end soon. For example, Spring Framework v.5 is supported for free only <a href="https://spring.io/projects/spring-framework#support" target="_blank">till the end of 2024</a>, and Spring Security v.5 even less, <a href="https://spring.io/projects/spring-security#support" target="_blank">till November 2023</a>. 

Unfortunately, with the upgrade of Spring libraries, Jmix 2.0 will no longer be able to include Classic UI based on Vaadin 8. The problem is that Vaadin 8 is incompatible with the new Jakarta Servlet API and Spring 6. 

As a result, to upgrade a project from Jmix 1.5 to Jmix 2.0, developers will need to migrate the application UI to Jmix Flow UI technology. The development approach in Flow UI is the same as in Classic UI: it's the server-side code with layout descriptors in XML and controllers in Java. But the UI components library, navigation, layout rules and many other things are significantly different. Because of this, migration from Classic UI to Flow UI can be a difficult and time-consuming task for any non-trivial project. 

According to our standard version support policy, the current Jmix 1.5 released in February 2023 should have been designated as LTS release because it is followed by the major version 2.0 in June 2023. Then the free support for projects on Classic UI would last for three years until February 2026. But we think that three years are not enough for a large project to upgrade its UI. Moreover, taking into account that many projects with Classic UI have just been started or are currently in active development, we would like to provide support for Classic UI beyond the previously announced scheme. 

So, we have decided to split the future release schedule into two branches. The main development will go as usual in a 4-month cycle: 1.5 → 2.0 (June 2023) → 2.1 (October 2023) → 2.x. In parallel, we will continue developing 1.x branch and make a couple of releases: 1.5 → 1.6 (in 2024) → 1.7 (in 2025). Release 1.7 will be the last release of version 1 and will get the LTS status. As a result, projects with Classic UI will have the free support for five years till 2028.  

![timeline.jpg]({{strapiUrl}}/uploads/Extended_Support_for_Classic_UI_timeline_ff8fd4311d.jpg)


The goal for 1.x branch is not only to provide critical fixes, but also to port important improvements in the backend from the main branch. The minor releases 1.6 and 1.7 will allow us to consolidate and deliver features that are too risky to include in patches. These releases will not follow the normal 4-month cycle, instead we'll build them when a particular amount of changes is accumulated, approximately once a year. 

Obviously, we are going to put our main effort into development of version 2 and further with Flow UI. In version 1.x, the Classic UI core will be frozen and mostly just receive bugfixes, while on the backend and in add-ons we will strive to also port all compatible improvements from version 2. We should also note that if some critical issue is found in an underlying library like Spring, and it is fixed in a version, incompatible with Jmix 1.x (for example in Spring Framework 6), we will not be able to integrate the fix into Jmix 1.x. In this case, we'll investigate the real impact and offer a workaround to mitigate it.  

One more thing about 1.x branch: Jmix 1.6 and 1.7 will not include Flow UI. So, if you currently have a project with Flow UI, upgrade it to Jmix 2.0 as soon as it's ready - there is no point to wait for 1.6. 

All that was written above about the split does not concern Studio. It will be released in the standard 4-month cycle (1.5 → 2.0 → 2.1 → 2.x) and all future 2.x versions will support Jmix 1.x projects. So developers of the projects with Classic UI will get all new Studio features, along with the support of the future IntelliJ versions. 

In conclusion, the summary of upcoming changes: 

- Jmix release 2.0 will include only Flow UI. 
- Classic UI development will continue in releases 1.6 and 1.7.  Classic UI will receive free updates for five years till 2028. 
- Jmix 1.5 is the last release containing both Classic UI and Flow UI.  
- Projects on Jmix 1.5 using Flow UI should upgrade to Jmix 2.0. Projects using Classic UI should upgrade to Jmix 1.6 and later to 1.7. 
- Studio version 2.x will support both Flow UI and Classic UI projects

The current state of supported versions is always available on the <a href="https://www.jmix.io/framework/versioning" target="_blank">Jmix Release Versioning</a> page. 

We hope that our extended support for Classic UI in Jmix 1.x will give enough time to application developers to achieve their goals and to prepare for migration to the latest technology stack provided by the newer Jmix versions. 
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar:  How to build rich and flexible CMS 2x times faster?]]></title>
            <link>https://www.jmix.io/blog/web-portal</link>
            <guid>https://www.jmix.io/blog/web-portal</guid>
            <pubDate>Mon, 24 Apr 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/1920x1080_fb4bd08559.png">In this webinar, we discussed the best approach for the development backend system with rich functionality. ]]></description>
            <content:encoded><![CDATA[In this <a href="https://www.youtube.com/live/nUqQI4QL2Zs?feature=share" target="_blank">webinar</a>, we discussed the best approach for the development backend system with rich functionality. You will learn why multi-awarded digital agency <a href="https://redcollar.co/" target="_blank">Red Collar</a> chose Jmix over PHP Laravel in their project. If you're looking for a powerful and flexible backend system for your webportal, don't miss out on this informative session.


<youtube data-video-id="nUqQI4QL2Zs"></youtube>

## The topics on webinar agenda:

+ <time-code data-time="0:00"> Introduction and agenda
+ <time-code data-time="2:25"> Assumptions
+ <time-code data-time="3:10"> Typical tasks for robust web-portal
+ <time-code data-time="3:59"> Backend development steps
+ <time-code data-time="5:05"> Jmix components
+ <time-code data-time="6:08"> Jmix architecture
+ <time-code data-time="7:29"> Backoffice UI
+ <time-code data-time="8:44"> UI attitude with Vaadin
+ <time-code data-time="9:50"> What about other UI technologies?
+ <time-code data-time="13:49"> Reasons for better productivity
+ <time-code data-time="15:29"> Red Collar case study: about Red Collar agency
+ <time-code data-time="17:34"> Project requirements
+ <time-code data-time="18:55"> Creative frontend
+ <time-code data-time="20:24"> Common architecture
+ <time-code data-time="23:50"> Data
+ <time-code data-time="26:16"> Why Jmix? Spring-compatible, scalable, secure
+ <time-code data-time="28:21"> Results of Red Collar case study
+ <time-code data-time="30:22"> Q&A




<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar:  Gaining cost savings and scalability for your digital products with multitenancy]]></title>
            <link>https://www.jmix.io/blog/multitenancy-webinar</link>
            <guid>https://www.jmix.io/blog/multitenancy-webinar</guid>
            <pubDate>Thu, 13 Apr 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Gaining_cost_savings_and_scalability_1920x1080_218232d0cb.png">How does Jmix help create Software-as-a-Service applications. Practical steps to implement multitenancy in your digital product.

]]></description>
            <content:encoded><![CDATA[In this <a href="https://www.youtube.com/live/bLji0OipbUw?feature=share" target="_blank">webinar</a>, we discussed how Jmix can help create Software-as-a-Service applications and the first steps to implement multitenancy in your digital product. Multitenancy is a significant feature for software vendors, providing substantial benefits in cost savings, and scalability, making it an essential element for the product strategy. 
Our battle-proven architectural concept for multitenant applications with high-productivity tools can help overcome the difficulties of transferring existing applications to a SaaS. Don't miss out on this opportunity to learn how to enhance your digital product. 

<youtube data-video-id="bLji0OipbUw"></youtube>

## The topics on webinar agenda:

+ <time-code data-time="0:00"> Introduction and agenda
+ <time-code data-time="4:03"> Tech stack and dev tools
+ <time-code data-time="4:54"> Multi instance application
+ <time-code data-time="6:40"> Moving to shared application
+ <time-code data-time="7:46"> What is multitenancy
+ <time-code data-time="8:51"> How does Jmix address multitenancy: Multitenancy add-on
+ <time-code data-time="11:13"> Multitenancy add-on: how does it work
+ <time-code data-time="12:41"> Configuring users
+ <time-code data-time="14:56"> Configuring security
+ <time-code data-time="17:16"> Cloud deployment
+ <time-code data-time="18:05"> Jmix supports SaaS through Cloud & Multitenancy
+ <time-code data-time="20:40"> Jmix Bookstore Example
+ <time-code data-time="28:53"> Power users
+ <time-code data-time="32:43"> Key takeaways about Jmix
+ <time-code data-time="36:40"> Q&A




<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix Positioning Recap 2022 ]]></title>
            <link>https://www.jmix.io/blog/positioning-recap-2022</link>
            <guid>https://www.jmix.io/blog/positioning-recap-2022</guid>
            <pubDate>Tue, 28 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Intercom_Jmix_a919f0af33.png">We were hard at work finalizing our product backlog scheduled for 2022 and finalizing marketing positioning, shaping a Less-Code platform concept. In this blog post, we will uncover the details of our recap the product positioning changes. ]]></description>
            <content:encoded><![CDATA[As the end of 2022 drew near, many of our readers and followers reached out to us, wondering why we had yet to publish our annual recap. We understand the anticipation, but we want to reassure you that it was not due to our lack of progress—quite the opposite. We were hard at work finalizing our product backlog scheduled for 2022 and finalizing marketing positioning, shaping a Less-Code platform concept. In this blog post, we will uncover the details of our journey and recap the product positioning changes. 

## Presenting Less-Code Concept 
In mid-2022, we first announced a new Less-Code platform concept during our webinar in July. In the <a href="https://www.jmix.io/blog/how-to-build-applications-faster/" target="_blank">webinar</a>, we’ve shown the major differences between Jmix and traditional Low-code. In short, we assumed Low-Code wouldn’t have strong popularity in the mid-term future, tending to move to the no-code space or toward professional programming. No code examples widely demonstrate good traction among power users, and we recognize their massive impact on citizen developers' engagement. Such technologies like Airtables, Bubble, Zappier, etc., have already become standard wording for the No-Code products. The main reason we don’t believe in Low-Code is their inability to gain a broad community because of their proprietary nature. Successful Low-code platforms are not isolated solutions. They are always parts of wider platform ecosystems like market leaders: Oracle APEX, Salesforce, and Mendix. They offer their Low-code integrated development platforms complementary to a core vendor platform technology. Recent news about upcoming AI code assistance progress (e.g., ChatGPT, Copilot) demonstrates a growing threat, especially for Low-Code areas without platform ecosystems. New capabilities for developers of any skill level eliminate the difficulty of writing code same time keeping in place the requirement to understand what you should write. This assures us that it will faster shift the focus to developers’ productivity technologies and tools connected with the professional development environment, assisted by AI. And this is precisely what Jmix does by representing a Less-Code paradigm. Summarizing the Less-code concept, we’ve published a dedicated section on the Jmix website uncovering the topic <a href="https://www.jmix.io/alternative-to-low-code-platforms/" target="_blank">“Is Jmix a low-code platform?”</a>. 

## Revisiting Jmix values 

Beyond that, we’ve invested in marketing research to discover how Jmix helps to reach tangible business results among the existing community. A year ago, we stated that we would focus more on those people who care about business results. Thus, our goal was to identify target personas, acquire feedback on Jmix values and put this information at the core of the product strategy. After performing a series of interviews, we identified the following target groups of users and explicit business requests, which Jmix addresses: 

![]({{strapiUrl}}/uploads/jmix_positioning_recap_67bfa308da.jpeg)

As a result of harmonizing the marketing investigation results, we came to the following set of Jmix values which will shape further product development roadmap: 

- Enables fast development of back-office applications implementing modern Java technology stack for companies and teams with a strict budget or time limitations; 
- Provides developers with an existing skillset a technology for fast prototyping of back-office applications, which can be transferred to enterprise-ready solutions built on Java technology stack; 
- Decreases the entry barriers and complexity of modern web development for beginners and developers from different programming technologies. 


We've launched an easy-to-use <a href="https://www.jmix.io/calculator/" target="_blank">ROI calculator</a> on the website to assist those who evaluate Jmix technology for future projects and need a tool to convince potential stakeholders. When it comes to business – it is usually about money. The ROI calculator tool helps to compare Jmix against two competitive approaches – Low-Code/BPM platform and Traditional development. Just make your business case data input, and it will show the ROI forecast. Please note that it can send a disposable calculation report in your e-mail. Visit the <a href="https://www.jmix.io/calculator/" target="_blank">ROI calculator</a> page for details. 

And the last but not less important part of our marketing improvements is the go-to-market strategy. In recent years, our partners have significantly boosted performance by providing localization, functional enrichment with add-ons, community growth, and sales support. “Think globally, act locally” becomes essential for product delivery. It also makes sense that end-users can purchase Jmix licenses and local services in their native language with the help of our channel partners. In 2022, we introduced three partnership levels – Value Added Reseller, Independent Software Vendor, and Authorized Service Provider. And if you and your company feel the power of Jmix, why not try it and upgrade our relationships by becoming an <a href="https://www.jmix.io/partners/" target="_blank">official partner?</a>


## How will it further impact the Jmix roadmap? 

Finally, we’ve considered the list of Jmix values internally and will develop the product according to them. Announcing this, we share our mindset to help you better understand our motivation in managing the Jmix roadmap and priorities when making decisions on feature design. In the next article, Product Manager Konstantin Krivopustov will go deeper into the technical details of the Jmix platform architectural concept and the mindset behind this. Stay connected and be productive. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: What's new in Jmix 1.5]]></title>
            <link>https://www.jmix.io/blog/jmix15-webinar</link>
            <guid>https://www.jmix.io/blog/jmix15-webinar</guid>
            <pubDate>Sat, 25 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/What_s_new_in_Jmix_1_5_1920e1080_cde30d7a31.png">In this webinar, we talked about new features and improvements in Jmix framework and Studio 1.5. We also took a closer look at the new features and discussed future plans.]]></description>
            <content:encoded><![CDATA[In this webinar, we talked about new features and improvements in Jmix framework and Studio 1.5. We also took a closer look at the new features and discussed future plans.

<youtube data-video-id="C4u6feUgxyM"></youtube>

## The topics on webinar agenda:
+ <time-code data-time="0:49"> Introduction
+ <time-code data-time="1:36"> Changes in Studio UX/UI
+ <time-code data-time="4:56"> New Flow UI components and APIs
+ <time-code data-time="15:52"> Flow UI for add-ons
+ <time-code data-time="17:57"> Excel export improvement
+ <time-code data-time="18:52"> Root Liquibase changelog contents
+ <time-code data-time="22:51"> Plans for Future releases
+ <time-code data-time="24:24"> Q&A



<style>
.blog-article__hero .blog-article__cover {
  display: none;
}

</style>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 1.5 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-1-5-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-1-5-is-released</guid>
            <pubDate>Tue, 14 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_1_5_f75b2002ab.png">Review of the most important updates introduced in Jmix 1.5 feature release.]]></description>
            <content:encoded><![CDATA[The new Jmix version 1.5 has been released recently. In this blog post, we'll explore the new features and enhancements included in this release. 

For full details and upgrade instructions, make sure to visit the <a href="https://docs.jmix.io/jmix/1.5/whats-new/index.html" target="_blank">What's New</a> page in the documentation.

## Studio UI/UX Changes

Let's begin with discussing the visible changes you'll notice in the updated Studio.

After several sessions of UX testing with developers who were unfamiliar with Jmix, we concluded that the current UI designer is overly complicated. With three tool windows and multiple XML/preview panels, it created a sense of confusion for those encountering it for the first time. On the other hand, we found out that people easily discover actions available on top of the current editor window and also tend to seek for available actions in context menus.

So we decided to get rid of the static components palette and move its contents into a popup window opened from different places: from the top actions panel, from the context menu of the component hierarchy, and from the **Generate** menu of the source code. The new popup supports search and drag-and-drop to the hierarchy or code:

![]({{strapiUrl}}/uploads/add_component_c2e995752a.gif)

The component hierarchy and inspector were merged into a single tool window named Jmix UI, which is located on the right side by default. Consequently, the UI designer now has only one tool window, and the component palette is easily accessible from multiple points in the interface.

Another problematic feature of the Studio interface was the **Code Snippets** palette. Despite being especially useful for inexperienced users, it could hardly be noticed by newcomers. Now the code snippets are available in a popup window that can be opened from the top actions panel and the **Generate** menu when editing Spring beans and UI controllers:

![]({{strapiUrl}}/uploads/code_snippets_c6da94227c.png)

## Flow UI Improvements

We continue working on the Flow UI features to bring it closer to the state when it can be used as a primary UI technology in Jmix.

In this release, we updated the core to Vaadin 23.3 and integrated several components.

### TabSheet

A tabsheet is essential when you need to fit a lot of UI components onto a single view. And this is a typical requirement in backoffice ERP-like applications where Jmix is most frequently used. 

In the previous release, Jmix provided only the Tabs component which was not a container and required programmatic switching between separate layouts. Thanks to Vaadin 23.3, we now have  the full-featured TabSheet with completely declarative layout:

```xml
<tabSheet width="100%">
    <tab id="mainTab" label="Main">
        <formLayout id="form" dataContainer="userDc">...</formLayout>
    </tab>
    <tab id="additionalTab" label="Onboarding steps">
        <vbox>
            <hbox>...</hbox>
            <dataGrid width="100%" dataContainer="stepsDc">...</dataGrid>
        </vbox>
    </tab>
</tabSheet>
```

<img src="{{strapiUrl}}/uploads/tabsheet_82503e880d.gif" width="677">

### MultiSelectComboBox

The `MultiSelectComboBox` component also appeared in the latest Vaadin allows a user to select multiple values from a drop-down and show them nicely in the field. We've integrated it into Jmix and added the data binding so you can use it to display and modify entity collection attributes. In the following example, the MultiSelectComboBox component is used to manage the many-to-many collection of tags for a product:

```xml
<instance id="productDc"
          class="com.company.demo.entity.Product">
    <fetchPlan extends="_base">
        <property name="tags" fetchPlan="_base"/>
    </fetchPlan>
    <loader/>
</instance>
<collection class="com.company.demo.entity.Tag" id="allTagsDc">
    <fetchPlan extends="_base"/>
    <loader id="allTagsDl">
        <query>
            <![CDATA[select e from Tag e]]]]><![CDATA[>
        </query>
    </loader>
</collection>
<!-- ... -->
<formLayout id="form" dataContainer="productDc">
    <textField id="nameField" property="name"/>
    <multiSelectComboBox property="tags" itemsContainer="allTagsDc"/>
</formLayout>
```

<img src="{{strapiUrl}}/uploads/multi_Select_Combo_Box_db2e321aa4.gif" width="337">


### Upload Fields

The Vaadin's Upload component serves as the foundation for two Flow UI components: `FileStorageUploadField` and `FileUploadField`. The former is designed to upload a file to the file storage and returns a `FileRef` object which is saved in an entity attribute. The latter returns a byte array which is directly saved in an entity.

The declarative usage of both components is straightforward - you just set a data container with the entity instance and the property name where to save a `FileRef` or byte array:

```xml
<fileStorageUploadField id="uploadField"
        dataContainer="userDc" property="picture"/>
```

### Image

The Image component also got the Jmix data binding. Now it can be easily used with an entity attribute of the `FileRef` or byte array type:

```xml
<image id="image"
        dataContainer="userDc" property="picture"
        height="280px" width="200px" classNames="user-picture"/>
```

To configure the image placement, use CSS styles. For example, to scale the image while maintaining its aspect ratio, create the following class and use it in the `classNames` attribute of the component:

```
.user-picture {  
    object-fit: contain;  
}
```

### Tooltip

Tooltips can display additional information about a UI component in a popup next to it. They appear on hover and keyboard focus.

For components supporting tooltips, the Studio UI designer shows the *Add* button in the inspector panel:


<img src="{{strapiUrl}}/uploads/tooltip_add_0fa58e7d64.png" width="386">

In the XML, the tooltip is defined in the nested element:

```xml
<textField id="nameField" property="name">
    <tooltip text="Product name" position="BOTTOM_START"/>
</textField>
```

<img src="{{strapiUrl}}/uploads/tooltip_66f01d5edc.gif" width="486">

### Generic Filter

One of the most popular components in the classic UI is Filter which allows users to select data based on different criteria, including entity properties, references, JPQL queries, and conditional operators. It's like a versatile Swiss Army Knife for structured data search - developers need only to include it in the screens and users can customize it and apply when needed.


In Jmix 1.5, we've added the GenericFilter component to the Flow UI with the basic feature: users can create any number of property conditions for the whole graph of entities. And as everything in Flow UI, the filter is fully responsive:

![]({{strapiUrl}}/uploads/filter_5c8834e9fe.gif)

You can configure the breakpoints where the filter changes its layout in the `responsiveSteps` nested element:

```xml
<genericFilter id="filter" dataLoader="usersDl"
			   summaryText="My filter">
	<responsiveSteps>
		<responsiveStep minWidth="0" columns="1"/>
		<responsiveStep minWidth="800px" columns="2"/>
		<responsiveStep minWidth="1200px" columns="3"/>
	</responsiveSteps>
</genericFilter>
```

Obviously, the filter should keep its state when navigating between views or refreshing the web page. Otherwise users will lose the filtering conditions, for example after editing a record in a detail view. The `queryParameters` facet provides automatic mapping of filter conditions to the current URL, which ensures the correct filter state when navigating and provides deep links including the filter conditions. The minimal configuration of the facet should just reference the filter component by its id:

```xml
<facets>
    <queryParameters>
        <genericFilter component="filter"/>
    </queryParameters>
</facets>
```

The development of the GenericFilter component is ongoing, and we intend to include all of the classic filter features in the Flow UI with the June 2023 release.

### Add-ons with Flow UI

In release 1.5, we have implemented Flow UI modules for the following popular open-source add-ons:

-   Multitenancy    
-   Quartz
-   Application Settings
-   Grid Export Actions

They are now available in the Studio add-ons marketplace when working on a project with Flow UI.

### Flow UI Menu

You might notice that the main menu in Flow UI is structured differently from the classic UI: each add-on has its own root node with a predefined order, and there is no common "Administration" menu. This default structure is good enough for experiments and prototypes, but for a real-world application you will need a completely customized menu. So you need to switch from the "composite" to the "single" menu mode and define your own structure.

Previously many developers refrained from using the "single" mode as much as possible because it led to a problem with including new add-ons in the project: their menu items didn't appear in the application menu and it was unclear how to add them.

Now this problem with the "single" mode is solved in the Flow UI menu designer. As soon as you switch to the "single" mode, the designer shows an additional panel on the left. It contains all menu items provided by the add-ons and available for use in the application. So when you include a new add-on, you can just open the designer and drag-and-drop the add-on menu to your custom application menu in a desired location.

![]({{strapiUrl}}/uploads/menu_designer_a63013d696.png)

## Excel Export

One of the very frequently used Jmix features is the ability to export data displayed in a UI table to Excel in one click. This feature was designed to export precisely the set of rows visible to the user at the moment, that is the current page selected with by a filter. But often users wanted to export all selected data instead of just the current page.

In release 1.5, we improved the `excelExport` action provided by the Grid Export Actions add-on to export all data if the user selects the "All rows" option in the export dialog. Loading of data is performed in batches for optimal performance and server memory usage.

The new behavior is available both for classic and Flow UI.

## Pessimistic Locking UI

The framework now provides a default UI for managing pessimistic locks. You can find it in the **Administration** menu of Classic UI and the **System** menu of Flow UI.

A system administrator can view the list of current locks and manually remove a lock if needed.

## Root Liquibase Changelog

Jmix has always done a great job helping developers to create and run Liquibase changelogs for database versioning. Studio generates changelogs for the difference between the data model and the database schema and runs them when starting the application. When a new version of the application starts in a test or production environment, it runs Liquibase to apply the schema changes on the connected databases.

But sometimes this simple workflow is not enough and developers need to run Liquibase outside of Studio or the application, for example, on a CI server using Liquibase CLI or Gradle plugin. 

Previously it was impossible because the root changelog file of the project didn't define changelogs provided by the add-ons. Jmix took the information about used add-ons from the project configuration and created the correct changelog dynamically in memory before running Liquibase.

Since Jmix 1.5, the root changelog file of the project is always complete and can be executed by Liquibase CLI or Gradle plugin. Studio automatically updates the includes whenever add-ons are added or removed. Also, when you start the application, Studio checks that includes in the root changelog correspond to the add-ons used in the project. If it finds a mismatch, Studio shows a notification dialog and suggests to add or remove includes.

The root changelog can be opened from the Jmix tool window by double-clicking on the **Liquibase** node of a data store: 

![]({{strapiUrl}}/uploads/root_changelog_151c454b78.png)


## What's next?

In the next feature release scheduled for June 2023, we are going to update the underlying stack of technologies to the latest major versions of Spring Framework, Spring Boot, EclipseLink and Vaadin. It will also require Java 17 as a baseline for developing and running applications.

Another important milestone will be implementation of Flow UI modules for the most frequently used Jmix add-ons: Reports and BPM.

Our detailed roadmap for the future releases is published as a [GitHub project](https://github.com/orgs/jmix-framework/projects/5). Patches for the current version 1.5 will be released approximately once a month to ensure regular updates. 

We welcome your feedback on our forum, and thanks to all who contributed with their ideas, suggestions and bugreports!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: What's new in Jmix 1.4]]></title>
            <link>https://www.jmix.io/blog/jmix-1-4-whats-new</link>
            <guid>https://www.jmix.io/blog/jmix-1-4-whats-new</guid>
            <pubDate>Tue, 29 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/jmix_1_4_17439c1e5f.png">In this webinar we talked about new features and improvements in Jmix framework and Studio 1.4. We also took a closer look at the new Flow UI and discuss future plans.  ]]></description>
            <content:encoded><![CDATA[In this webinar we talked about new features and improvements in Jmix framework and Studio 1.4. We will also took a closer look at the new Flow UI and discussed future plans.  


<youtube data-video-id="kMg3wlSmSxM"></youtube>

## The topics on webinar agenda:

+ <time-code data-time="0:49"> Introduction
+ <time-code data-time="1:28"> Stable Flow UI core
+ <time-code data-time="17:37"> Improvements in the Jmix tool window
+ <time-code data-time="19:58"> Autorization server
+ <time-code data-time="22:01"> Studio improvements
+ <time-code data-time="24:39"> A wizard for creating row-level roles and policies
+ <time-code data-time="26:07"> New framework extension points
+ <time-code data-time="28:04"> Q&A





<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 1.4 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-1-4-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-1-4-is-released</guid>
            <pubDate>Tue, 15 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/jmix_1_4_96359c4a5a.png">Review of the most important updates introduced in Jmix 1.4 feature release.]]></description>
            <content:encoded><![CDATA[The new Jmix version 1.4 has been released recently. In this article, I will highlight key updates introduced in this feature release.

As usual, for the full information on changes and upgrade instructions, check out the <a href="https://docs.jmix.io/jmix/1.4/whats-new/index.html" target="_blank">What's New</a> page of the documentation.


## Stable Flow UI Core

The most prominent change is no doubt the stable core of the Flow UI module based on Vaadin 23. Now you can use it for creating new projects and expect normal evolution of the API and features in the future, with backward compatible patches and possible minor incompatibilities in feature releases.

Flow UI allows you to build responsive mobile-friendly applications without any special effort, using the same server-side Java programming model and XML layout supported by the visual designer in Studio. 

From the user experience point of view, Flow UI applications are closer to regular web apps than applications built with the classic Jmix UI. CRUD views now have unique URLs that can be used as deep links to the application functionality. There are no more inner tabs in the main window, but the main menu allows users to open views in separate browser tabs or windows using the browser's context menu or Ctrl/Cmd+Click.

![]({{strapiUrl}}/uploads/flowui_1_9caccfa4e0.gif)

The new visual designer for Flow UI has a preview panel which shows the exact look of the view considering the application theme and specific styles of the components. Also, it has a significant difference from the classic UI designer: there is no Palette tool window. Instead, use the Add Component action available through the top actions panel, Component Hierarchy context menu and Generate menu (Alt+Ins / Cmd+N).

![]({{strapiUrl}}/uploads/flowui_designer_1_b9423569f0.png)

The Jmix Flow UI is still on the early stage and we have a lot to do to make it as feature-rich as the classic UI. Many important features, such as generic filter, inline editing in DataGrid, background tasks, input dialogs are missing now and will be implemented in the next release. 

Currently, Flow UI modules are available for the security subsystem (roles, policies), Audit and Data Tools add-ons (Entity Log, User Sessions, Entity Inspector). So in the projects with Flow UI, you can use these add-ons and the add-ons without UI like REST, OIDC, file storages and so on. Other important add-ons will get Flow UI in the future releases next year.

## Studio Improvements

Jmix Studio 1.4 got a few useful enhancements.

The **Configuration** section of the Jmix tool window now displays all classes annotated with `@Configuration` and its derived annotations (e.g. `@SpringBootApplication`), `@ConfigurationProperties` classes, as well as REST queries and services configuration files:

<img src="{{strapiUrl}}/uploads/config_section_7e4bf14598.png" width="478">

Spring beans having methods with an entity in the arguments or the result are shown in the **Beans** section of the entity:

![]({{strapiUrl}}/uploads/data_model_beans_aa6e2d64cd.png)

The **Inject** action for Spring beans now supports constructor injection, which is considered a best practice. To use it instead of the field injection, select the **Use constructor injection** checkbox, and Studio will create a final field and a constructor argument:

![]({{strapiUrl}}/uploads/constructor_injection_1_74eb527d4e.png)

```java
@Component
public class CustomerService {

    private final DataManager dataManager;

    public CustomerService(DataManager dataManager) {
        this.dataManager = dataManager;
    }
```

The new wizard will help you create row-level roles. To create a role, click **New → Row-level Role** in the Jmix tool window and enter role parameters in the dialog:

<img src="{{strapiUrl}}/uploads/rl_role_1_aa3f48d337.png" width="1000">

Studio will create the annotated role class. You can add policies using the **Add Policy** actions:

![]({{strapiUrl}}/uploads/rl_role_2_3f4661a751.png)

Now you can have a custom set of project templates tailored for your organization. 

This feature works as follows: You build a JAR file with the templates and publish it in the custom artefact repository. Developers set the artefact coordinates in the IDE settings and choose the custom repository in the **New Project** wizard. Then Studio loads both standard templates (if their artefact is present in the repository) and custom ones, and shows the joined list of templates to the developer.

For more details on building the custom templates artefact see the <a href="https://docs.jmix.io/jmix/whats-new/index.html#custom-project-templates" target="_blank">documentation</a>.

## Framework Improvements

We've added a couple of extension points to the security subsystem.

The first one is in the process of changing passwords by users. You can provide password validators as Spring beans implementing the `PasswordValidator` interface:

```java
@Component
public class MyPasswordValidator implements PasswordValidator<User> {

    @Override
    public void validate(PasswordValidationContext<User> context) throws PasswordValidationException {
         if (context.getPassword().length() < 3)
            throw new PasswordValidationException("Password is too short, must be >= 3 characters");
    }
}
```

Another extension point is in the Spring security configurations provided by the framework and add-ons. Previously, to adjust a configuration, you had to copy-paste the entire configuration to your project. Since Jmix 1.4, you can just create a `AbstractHttpConfigurer` bean with your specific logic and give it a qualifier which identifies the inherited configuration to adjust:

```java
@Component
@Qualifier(StandardSecurityConfiguration.SECURITY_CONFIGURER_QUALIFIER)
public class MySecurityConfigurer extends AbstractHttpConfigurer<MySecurityConfigurer, HttpSecurity> {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        MyFilter myFilter = new MyFilter();
        http.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class);
    }
}
```

Now you can lock on the database level when loading entities by `DataManager`. Its fluent loader interface accepts the `javax.persistence.LockModeType` enum values in the `lockMode()` method:

```java
var customer = dataManager.load(Customer.class)
        .id(customerId)
        .lockMode(LockModeType.PESSIMISTIC_WRITE)
        .one();
```

When working with JPA entities, it effectively leads to executing the `select …​ for update` SQL statement.

## Jmix Authorization Server Preview

The current Jmix Security OAuth2 module which is used for issuing tokens when working with REST is based on the now deprecated Spring Security OAuth project. Also, it implements only the <a href="https://www.rfc-editor.org/rfc/rfc6749#section-1.3.3" target="_blank">Password Grant</a> which is not recommended by the OAuth specification.

To solve both problems, we've built a new OAuth module based on the modern Spring Authorization Server project. It supports the <a href="https://www.rfc-editor.org/rfc/rfc6749#section-1.3.1" target="_blank">Authorization Code</a> and <a href="https://www.rfc-editor.org/rfc/rfc6749#section-1.3.4" target="_blank">Client Credentials</a> grant types. 

The Jmix Authorization Server is in the preview stage and will be improved based on your feedback. See the module documentation in the project's <a href="https://github.com/jmix-framework/jmix/blob/master/jmix-authorization-server/README.md" target="_blank">README</a>.

## What's next?

In the upcoming months we are going to bring the Flow UI core features to the level comparable with the classic UI and provide Flow UI modules for the most important add-ons like BPM, Multitenancy and Reports.

In Studio, we will improve stability and introduce a new way of creating UI for data model elements.

Our detailed roadmap is published as a <a href="https://github.com/orgs/jmix-framework/projects/5" target="_blank">GitHub project</a> and updated regularly.

We are also constantly working on fixing issues in the current release 1.4. Patches 1.4.x will be released approximately once a month. 

We'll be glad to see your feedback on our <a href="https://forum.jmix.io" target="_blank">forum</a>!
Thanks to all who contributed with their ideas, suggestions and bugreports! 
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Got stuck with BPM limitations while implementing business processes automation?]]></title>
            <link>https://www.jmix.io/blog/bpm-development</link>
            <guid>https://www.jmix.io/blog/bpm-development</guid>
            <pubDate>Mon, 07 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/1920e1080_2_9ea5782a65.png">On this session we talked about BPMS in modern world and what Jmix can give you to proceed with business digitalization in the most effective and cost-effective way.
]]></description>
            <content:encoded><![CDATA[On this session we talked about BPMS in modern world and what Jmix can give you to proceed with business digitalization in the most effective and cost-effective way.

<youtube data-video-id="1Q314WJVmeA"></youtube>

## The topics on webinar agenda:

+ <time-code data-time="1:42"> Introduction.
+ <time-code data-time="3:02"> History of BPMN
+ <time-code data-time="5:09"> Why should I care about BPMN in 2022?
+ <time-code data-time="6:16"> Evolution of BPMN
+ <time-code data-time="8:22"> Business processes automation nowadays
+ <time-code data-time="9:19"> Typical BPM limitations: data validation, siloed data, integrations, business logic
+ <time-code data-time="11:46"> Jmix approach
+ <time-code data-time="13:59"> Open-source advantages
+ <time-code data-time="14:53"> About Jmix
+ <time-code data-time="15:29"> Components of Jmix.
+ <time-code data-time="16:18"> BPM designer in Jmix
+ <time-code data-time="16:39"> How to use BPM addon
+ <time-code data-time="16:57"> Demo scenario. Practical example: Jmix bookstore. Different roles of users
+ <time-code data-time="21:19"> Development process of performing a supplier order in Jmix
+ <time-code data-time="31:09"> Process instance editor in Jmix
+ <time-code data-time="37:41"> Implementing notification on new order
+ <time-code data-time="38:59"> Administrative possibilities to manage system




<style>

.blog-article__hero .blog-article__cover {
  display: none;
}

</style>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Engage with your users through in-app Chat Support | Guide]]></title>
            <link>https://www.jmix.io/blog/engage-with-your-users-through-in-app-chat-support</link>
            <guid>https://www.jmix.io/blog/engage-with-your-users-through-in-app-chat-support</guid>
            <pubDate>Mon, 05 Sep 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Intercom_Jmix_a919f0af33.png">Take a look at how to enrich your Jmix application with the ability to directly interact with your users via chat. Get a very direct connection to your users, understand how they use the software, and see problems/questions that arise during the usage.]]></description>
            <content:encoded><![CDATA[When you build software, how do you know what your user wants? Not in the abstract sense of the term, but exactly – how do you know for sure? The only answer bringing you to this knowledge is that you have to either ask your users or let your users tell you. The more concrete, actionable, and raw feedback you want to get, the closer you get with your users.

For developers, this knowledge is probably one of the most valuable, as it is not coming through any form of indirection. There is no survey, no product manager that aggregated and interpreted the feedback or anything else that sits between you and your user.

But how can this communication channel be created? Email? Support Forum? Fine, but what if we can contextualize the conversation a little more and also make it on-the-spot? Inside the application with low friction to start such a conversation. The chance that someone will “just start chatting” with you seems very high. In particular, higher compared to someone heading over to your support forum, creating an account, searching for similar posts, trying to articulate the problem, uploading screenshots, etc. To get an answer (or no answer) three days later.

Let’s look into this topic and explore how you can enable such functionality inside your application. You could build such a support chat system directly into your app, but normally the user experience and quality will be not very good and the feature set will be comparably small as it is not directly related to your core domain. Second of all, building that right is going to be a tremendous effort.

## Introducing Intercom

Luckily, there are solutions out there in the market that you can utilize. This increases the quality of the result drastically, but it also lets you focus on the core domain of your business. In this case, we will integrate Intercom into the Jmix Petclinic application as an example. Besides the chat system of Intercom, it has some more advanced customer support features. We will explore what we can use further from their offering to provide the users of the Petclinic a great customer support experience.

In our example use case, we will focus on the support that is provided to the Nurses of the Petclinic. We want them to have the ability to ask general questions about the Software, but also specific help when questions arise during the Treatment of Pets. For this, we will imagine Veterinarians sitting on the other side of the chat system (using the Intercom Inbox application) to help with support requests.

## Integrating Intercom Messenger into the Petclinic

The first thing we need to do is to integrate the Intercom Messenger component into our Jmix application. Intercom provides the Messenger as a small JavaScript component that should be added to the website that wants to provide chat features. In our case of Vaadin, we need to integrate a JavaScript library as an <a href="https://vaadin.com/docs/v8/framework/articles/IntegratingAJavaScriptLibraryAsAnExtension" target="_blank">Extension</a>.

There are three parts of it:

1. The client-side JavaScript code: <a href="https://github.com/mariodavid/jmix-petclinic-intercom/blob/main/src/main/resources/io/jmix/petclinic/widgets/intercom.js" target="_blank">intercom.js</a> 
2. A State class that represents the data that can be exchanged from the Java API to the client side: <a href="https://github.com/mariodavid/jmix-petclinic-intercom/blob/main/src/main/java/io/jmix/petclinic/widgets/client/IntercomState.java" target="_blank">IntercomState.java</a>
3. A server-side Extension class that binds together the client-side JavaScript code and provides a Java API: <a href="https://github.com/mariodavid/jmix-petclinic-intercom/blob/main/src/main/java/io/jmix/petclinic/widgets/IntercomIntegration.java" target="_blank">IntercomIntegration.java</a> 

More information about the implementation you can find in the <a href="https://github.com/mariodavid/jmix-petclinic-intercom#jmix-petclinic-intercom-widget-integration" target="_blank">README</a> of the example project.

With that component in place, we create an instance of it within the Main Screen of the Petclinic application:

```java

@UiController("petclinic_MainScreen")

@UiDescriptor("main-screen.xml")

@Route(path = "main", root = true)

public class MainScreen extends Screen implements Window.HasWorkArea {

  // ...

  @Subscribe

  public void onBeforeShow(BeforeShowEvent event) {

    IntercomIntegration intercom = new IntercomIntegration("<<intercomAppId>>");

    intercom.setUserEmail(currentUser().getEmail());

    intercom.setUserId(currentUser().getId().toString());

    intercom.extend(UI.getCurrent());

    intercom.setUserData("name", currentUser().getDisplayName());

    intercom.setUserData("background_color", "#867AEB");

    intercom.setUserData("action_color", "#4D3DE1");

  }

  private User currentUser() {

    return (User) currentAuthentication.getUser();

  }

  // ...

}

```

With that in place, the Petclinic has now a basic chat functionality. It is possible to start chat conversations from within Jmix.

![picture]({{strapiUrl}}/uploads/1_petclinic_intercom_messenger_Ctz0v_37d8f924d7.png)

By setting additional data as part of the initialization process, we also send contact information to Intercom like the Email Address, First name, and Last name of the current user. Within Intercom the conversations are visible as well, so that the Vet can use this UI to have an overview of all incoming support requests:

![picture]({{strapiUrl}}/uploads/2_intercom_inbox_Yl_T2_W_21ba72c61f.png)

## Contextual Information within the Intercom Inbox

Having the basic contact information available for the Vets is a good start. But to avoid switching back and forth between the Petclinic application and the Intercom Inbox, it would be good to have the context of the conversation. For the conversation with a Nurse, it might be information about upcoming Visits.

Intercom allows us to enrich the Inbox UI with more data as well as immediately trigger actions from within the Inbox. Let’s look at the first use case: showing upcoming visits that are assigned to the Nurse who has initiated the conversation.

Let's start by looking into the result and then we will explain how we can achieve this:

![picture]({{strapiUrl}}/uploads/3_petclinic_information_in_intercom_inbox_c_F0fr_a7e1df6c53.png)

As you can see on the side menu of the Inbox, we added an extra section called “Petclinic Information”. It displays upcoming visits of pets that are already assigned to “Nurse Joy”. When switching to another conversation, this side menu is updated according to the conversation partner.

Let’s look into how this is done from a technical perspective. When a conversation is opened, Intercom performs a webhook call to the Petclinic application. The result of that webhook request is a specific JSON response representing the UI that Intercom is rendering in the side menu.

![picture]({{strapiUrl}}/uploads/4_owner_sync_dee925f077.png)

The JSON that defines the UI contains the layout and the data that are displayed. A REST Controller in the Petclinic application called <a href="https://github.com/mariodavid/jmix-petclinic-intercom/blob/main/src/main/java/io/jmix/petclinic/intercom/canvaskit/petclinic_information/PetclinicInformationController.java" target="_blank">PetclinicInformationController</a> is receiving this webhook. The request contains information about the conversation. With that, it is possible to extract the Email address of the conversation partner. The code performs a lookup of the User and checks if the User is a Nurse. If this is the case, it will load the most recent visits associated with the user.

```java

List<Visit> latestActiveVisitsForUser = 
systemAuthenticator.withSystem(() ->,
  visitRepository
    .latestActiveVisitsForUser(data.getContact().getExternalId())
);

```

After loading the data, it will create a JSON object that represents the UI and send it back as a response of the webhook:

```json

{ 
  "canvas": { 
    "content": { 
      "components": [ 
        { 
          "id": "text", 
          "style": "header", 
          "text": "Upcoming Visits", 
          "type": "text" 
        },
        { 
          "type": "divider" 
        }, 
        { 
          "items": [ 
            { 
              "id": "ea31793b-866a-03a5-5764-69e5cadc14b7", 
              "title": "Goldeen", "subtitle": "Other", 
              "tertiary_text": "28. June 10:00",
              "image": "...", 
              "image_width": 32, 
              "image_height": 32, 
              "disabled": false, 
              "action": { 
                "url": "https://jmix-petclinic-intercom.herokuapp.com/#main/visits/edit?id=7a65wkq1ka0ejnes39wq5dr55q",
                "type": "url" 
              }, 
              "type": "item" 
            }, 
            { 
              "id": "a6e254a9-ac3d-1441-455c-44cd8cf99d81", 
              "title": "Crobat", 
              "subtitle": "Regular Checkup", 
              "tertiary_text": "28. June 11:30", 
              "image": "...", 
              "image_width": 32, 
              "image_height": 32, 
              "disabled": false, 
              "action": { 
                "url": "https://jmix-petclinic-intercom.herokuapp.com/#main/visits/edit?id=56w9aakb1x2h0maq24sp6fk7c1", 
                "type": "url" 
              }, 
              "type": "item" 
            }
          ], 
          "type": "list" 
        } 
      ] 
    } 
  } 
}

```

## Recent user actions in the Intercom Inbox

Another integration example is the ability to show actions performed lately by a user. Intercom allows storing custom events for a particular contact. This way it is possible to create an event in Intercom when a particular situation in the Petclinic application occurs, like the start of a Treatment. Furthermore, Intercom allows you to proactively reach out to the user via the chat system when a particular event occurs.

As an example, we will notify Intercom when a Treatment started via a custom event. Then we will use a custom chatbot to create an outbound conversation to ask if the Nurse has any questions.

As part of the UI controller for the “My Visits” UI, we will extend the controller to send an event to Intercom:

``` java
  intercomNotifications.notify(
    TreatmentStartedEvent.builder() 
      .visit(visit) 
      .build() 
  );
```

The <a href="https://github.com/mariodavid/jmix-petclinic-intercom/blob/main/src/main/java/io/jmix/petclinic/intercom/notification/IntercomNotifications.java" target="_blank">IntercomNotifications</a> bean that is responsible for sending out the events, is using the <a href="https://github.com/intercom/intercom-java" target="_blank">Intercom Java SDK</a> which performs API requests against the <a href="https://developers.intercom.com/intercom-api-reference/reference/submitting-events" target="_blank">Data Events REST API from Intercom</a>. This results in new events showing up in the custom events section of the Intercom Inbox.

![picture]({{strapiUrl}}/uploads/5_recent_events_in_intercom_inbox_w_DC_Zv_b5bb694918.png)

As you can see, the events can also carry arbitrary custom attributes, which makes it quite flexible to provide additional information to the Inbox user.

Although this functionality has value in itself, let’s enrich the experience for the Nurse as well by proactively asking for further assistance when this event occurs.

![picture]({{strapiUrl}}/uploads/6_event_based_bot_overview_3r_Fq_Z_0be1947564.png)

To achieve this, we need to configure a Bot in Intercom. The starting event is our newly created custom event: “treatment-started” (1).

Then the behavior of the bot is configured — (2) and (3) — to start a conversation and provide a couple of possible answers to a Nurse.

If the answer is “Yes, please!”, the bot asks a couple of questions to determine which Visit it is about and what questions the Nurse has. All of this information is then transferred to a Vet as a Conversation in Intercom.

![picture]({{strapiUrl}}/uploads/7_event_based_bot_questions_Ezcgk_9fe9a913a7.png)

The result of the combination of a custom event and the configured bot looks like this:
<div class="youtube-video">
<iframe src="https://www.youtube.com/embed/ZHWXl0Wcowc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>

## Summary

As you have seen with those examples, it is possible to enrich your Jmix application with the ability to directly interact with your users. With that, it gives you the possibility to get a very direct connection to your users, understand how they use the software, and see problems/questions that arise during the usage. With the ability to proactively start a conversation via bots, you can also make the user aware of the ability to get in contact with you.

To give you more contextual information, it is also possible to give a support person a custom-tailored experience directly in the support tool of choice (in this example it is Intercom, but different vendors have similar capabilities).

Besides this, we also looked into the technical details on how to integrate Jmix with external systems like Intercom. You saw two major interaction patterns: webhooks & REST API usage. There are a couple of more examples implemented and explained in the README: <a href="https://github.com/mariodavid/jmix-petclinic-intercom" target="_blank">https://github.com/mariodavid/jmix-petclinic-intercom</a> .]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Simplicity & Focus Through Server-Driven Web UI Development]]></title>
            <link>https://www.jmix.io/blog/simplicity-focus-through-server-driven-web-ui-development</link>
            <guid>https://www.jmix.io/blog/simplicity-focus-through-server-driven-web-ui-development</guid>
            <pubDate>Tue, 16 Aug 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Single_Language_424d968b4a.png">Being a full-stack developer is a complex undertaking these days. As you might remember, it hasn't always been like this. There are multiple reasons for this evolution.]]></description>
            <content:encoded><![CDATA[Being a full-stack developer is a complex undertaking these days. As you might remember, it hasn't always been like this. There are multiple reasons for this evolution. One example is ever-growing responsibilities (think of DevSecOps). Another is specialised tooling for different aspects of the stack getting more and more complicated. 

In particular, the UI aspects have increased in complexity over the years. There are various factors motivating it. One of the most important ones is the rise of single-page application frameworks (SPAs). A JavaScript frontend that uses API calls to display data or perform some action requires to build HTTP APIs for all UI-related interactions. For many types of back-office applications those APIs represent accidental complexity.  

Jmix, being a full-stack business application framework, offers the server-side development approach with the help of Vaadin. Let's see how it works and why removing the dividing line between frontend and backend helps in a lot of scenarios. 

## What is server-driven web UI development with Jmix & Vaadin? 

Server-driven web UI development generally means that the UI and the server side are closely working together to perform some business functionality. In this architecture, the UI and the backend of a business domain have a high cohesion as they provide a particular business feature together.  

Let’s compare this to the SPA approach, where the frontend and the backend have a clear and strong dividing line through an explicit API. The coupling is much lower in this scenario as the two parts only communicate through an explicit contract.  

Generally speaking, having low coupling is considered beneficial between independent components. But are the UI and backend actually independent from one another, or do they actually form a single logical component? If this is the case, having a high cohesion is actually desirable, as this is the nature of a single component. 

In case of back-office UIs, the frontend and backend functionality are closely aligned. Therefore, the cost of introducing low coupling between the UI and the server side is very high. It brings no additional value but causes harm in terms of efficiency and unnecessary decoupling. 

With the server-driven UI the frontend and backend code is often written in the same programming language.  

For web applications, this has previously partly been possible for an application that used server-rendered HTML. In the Java world, solutions like JSP or Thymeleaf were using this approach to create the user interface with the help of Java. There are domain-specific languages / APIs, but the language was mostly the same. Still, developers had to learn the basics of the web with HTML & CSS. 

With the rise of JavaScript and SPAs in particular, where more and more logic went to the web browser, using the same language was becoming less popular. Yet powerful frameworks emerged that make server-side driven web UIs possible, like Phoenix Liveview, Blazor for C#, or Vaadin in the Java ecosystem.  

Conceptually they all follow the same principle: the application developer writes UI logic in their preferred backend languages like Elixir, C#, or Java. The framework performs some translation to make this available in the browser. This way, the developer does not have to think about the frontend and backend as separate components only due to technological restrictions. 

## How Vaadin works 

Vaadin (Vaadin Flow to be more precise) is a set of web components and a Java API. An application developer writes the UI layout arrangement in Java. Vaadin uses this information to create the corresponding UI components in the browser.  

When the user interacts with the components (like clicking a button), it creates a call-back to the server that triggers the corresponding Java method declared as an event listener.   

The framework takes care of the interaction between the browser and the server, so no explicit API is needed to connect your UI to the backend.  

It also keeps track of each user session and the state on the server to perform the corresponding dispatch of the method invocations.   

In a strong frontend-backend separation the client code normally performs dedicated API calls via JavaScript to trigger an action on the server-side. As the majority of interactions reside on the client, very few manual API calls are performed. Vaadin, on the other side, transfers the majority of UI interactions to the server. 

Let’s look at an interaction example. Jmix Petclinic example contains a calendar view for the visits for a particular month:    

![blog-post-image-1.png]({{strapiUrl}}/uploads/blog_post_image_1_9ea78943a3.png)

There are two buttons to change the month to display. When clicking the button, the following Java code is executed and the UI in the browser is refreshed with the visit data of the previous month:   

```
@UiController("petclinic_Visit.browse")
@Route(value = "visits")
public class VisitBrowse extends StandardLookup<Visit> {
    //...
    @Subscribe("navigatorPrevious")
    protected void onNavigatorPreviousClick(Button.ClickEvent event) {
        calendarNavigators
                .forMode(
                        CalendarScreenAdjustment.of(calendar, calendarNavigator, calendarTitle),
                        datatypeFormatter,
                        calendarMode.getValue()
                )
                .navigate(PREVIOUS, calendarNavigator.getValue());
        loadEvents();
    }
}
```

The interaction performed by Vaadin is the following:  

![sequence-diagram.svg]({{strapiUrl}}/uploads/sequence_diagram_335397c5a4.svg)

The JavaScript part of Vaadin (Vaadin Client) handles the button click on the browser and delegates the request to the backend part of the Vaadin component (Vaadin Server). This will lookup the context and the current user session. Afterwards Vaadin dispatches the click event to the Java UI code on the server-side.  

The UI code will update the calendar component and refresh the data. This happens by interacting through the Vaadin Java API to update some Vaadin components. The Vaadin Server component will pick up the components to update and transfer the new component state to the Vaadin Client in the browser. This will mirror the requested updates in the browser so that the user can finally see the previous month data.  

## What Jmix adds to the table 

Jmix is a <a href="/rapid-application-development/">Rapid Application Development</a> framework for building data-centric business applications. One of its cornerstones is Vaadin as a UI rendering engine. Jmix enables declarative creation of the UI layout in XML, which is less verbose than programmatic building of UI in Java, as is done with pure Vaadin. The XML layout can be edited manually or in the visual designer. Jmix Studio is a tool based on IntelliJ IDEA. It provides the described functionality.  

Jmix also provides features specifically targeted at enterprise applications, such as large collections of data-aware UI components extending the Vaadin library. One example is a sophisticated filter component allowing end users to construct arbitrary filtering conditions.   

Besides, it comes with a set of modules providing optional features: from data access control and audit to reporting and business process management. Many Jmix modules include a user interface, which seamlessly integrates into the resulting full-stack application. And this inherited UI can be easily customised in the application, thanks to Vaadin's server-side programming model and extendable Jmix UI layouts written in XML. 

## Benefits of server-driven UI development 

This approach has a couple of advantages compared to the frontend-backend separation, but it is also only beneficial under particular circumstances. 

### Reduced complexity 

First of all, it removes cognitive load, as the overall solution is simpler from a developer's point of view. No need to think about two ecosystems to program in lets the developer focus more on the value-add of the application you want to produce. Java developers can leverage their existing knowledge for topics like debugging, dependency management, static code analysis tooling, testing approaches, etc.  

Abstraction, on the other hand, is always a double-edged sword. It is good as long as there is no need to look under the covers. Therefore, in some scenarios, it is absolutely crucial to have access to the JavaScript ecosystem in its entirety. This is not so easy when using Vaadin compared to a dedicated JavaScript SPA in place. 

One additional technical benefit is that there is little code duplication. In Jmix / Vaadin you use the same domain models for your business logic as for your UI. Removing duplication significantly drives down complexity. Validation logic is kept in one place and does not have to be mirrored in the UI code and the backend API code.  

### Security

From a security point of view, Vaadin’s architecture also has some benefits. It never exposes its internals to the browser and instead only sends to the web browser the exact data that is required to update the UI. This is an inherently more secure development approach compared to the situation where it is up to the developers to transfer the right data for a particular UI interaction. This can lead to too much data exposed to JavaScript by API endpoints. 

### Full-stack teams  

When working in cross-functional teams with a strict frontend-backend separation, it often leads to the situation that the team itself divides on this line, as the different areas need dedicated expertise. Here the architecture drives the sub-team boundaries as commonly known by Conway's Law. In this case, it is an unfortunate development that leads to developers having a harder time thinking about the whole end-to-end business process as they are only responsible for one part.   

Full-stack developers can clearly see the implications of modelling something in the data model and what problems/benefits it might bring to the UI parts. Vaadin promotes this model implicitly, as it reduces the entry barrier for backend developers to do frontend-related work.  

This also brings another interesting benefit to the table. When having small teams, Single Language Development enables them to still bring the whole application to life. It does not require dedicated frontend developers in the teams.  

On the other hand, for a lot of frontend developers, this approach of developing the UI with backend technologies is quite uncommon. Therefore, based on the existing team structure, it can either be a benefit or a drawback. 

## Limits of Vaadin’s UI approach 

The architectural Vaadin  approach is not a silver bullet. The fact that every UI session is represented on the server puts a certain memory burden on the backend. This is fine for most business applications, where the number of concurrent users is tens of thousands, not millions. But an application with tens of millions of concurrent users working with UI would require a tremendous amount of memory.   

When it comes to Jmix and the focus on business applications, this limitation is not a real problem. But there are applications that have a public customer-facing part in addition to the back office where this huge number of concurrent users could come from. In this case, a hybrid approach with a REST API for the particular use-cases of the public frontend combined with an additional SPA mitigates this limitation.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Webinar: How to make prototype and build business apps faster?]]></title>
            <link>https://www.jmix.io/blog/how-to-build-applications-faster</link>
            <guid>https://www.jmix.io/blog/how-to-build-applications-faster</guid>
            <pubDate>Sun, 31 Jul 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/1_How_to_make_prototype_and_build_business_apps_faster_1920e1080_4_2e4208add1.png">In this session, we took a deeper look at how to make a massive impact on developer productivity. We discussed how you can build enterprise applications faster, increase time to value and decrease software license spending with open-source.]]></description>
            <content:encoded><![CDATA[In this session, we took a deeper look at how to make a massive impact on developer productivity. We discussed how you can build enterprise applications faster, increase time to value and decrease software license spending with open-source.

<youtube data-video-id="yt7iKlwDmbE"></youtube>

## The topics on webinar agenda:

+ <time-code data-time="5:13"> Introduction and agenda
+ <time-code data-time="9:37"> Exploring ways to deliver applications faster: Traditional development, No-Code, Low-Code, Less-Code
+ <time-code data-time="17:13"> Exploring developer personas
+ <time-code data-time="21:22"> Major difference between development approaches
+ <time-code data-time="23:56"> Comparison metrics: UI agility, business logic agility, time to market, integration capabilities, vendor independency
+ <time-code data-time="25:13"> Technology comparison radar
+ <time-code data-time="29:25"> Less-code platform: Jmix
+ <time-code data-time="30:48"> Jmix platform components
+ <time-code data-time="35:15"> Beyond development
+ <time-code data-time="37:46"> Jmix target applications
+ <time-code data-time="40:29"> A broad spectrum of applications
+ <time-code data-time="41:21"> A perfect tool for legacy migration
+ <time-code data-time="45:14"> Best option for ISVs
+ <time-code data-time="51:06"> Key takeaways about Jmix
+ <time-code data-time="56:20"> Q&A

<style>
.blog-article__hero .blog-article__cover {
  display: none;
}

</style>
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 1.3 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-1-3-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-1-3-is-released</guid>
            <pubDate>Tue, 12 Jul 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/JMIX_1_3_84211d55ee.png">The new Jmix version 1.3 has been released recently. In this article, I will highlight the most important updates introduced in this feature release.]]></description>
            <content:encoded><![CDATA[The new Jmix version 1.3 has been released recently. In this article, I will highlight the most important updates introduced in this feature release.

As usual, for the full information on changes and upgrade instructions, check out the <a href="https://docs.jmix.io/jmix/1.3/whats-new/index.html" target="_blank">What's New</a> page of the documentation.

## Java 11 Is Required

Probably the most important thing to note before upgrading is that Java 8 is not supported anymore. The framework is now built with Java 11, so you have to use Java 11 or above to build and run your applications.

The main motivation for abandoning Java 8 was introducing of the experimental FlowUI module based on Vaadin 23 (see below), which required Java 11. We decided that it's time to move on and also enjoy little language and standard library enhancements available in Java 11.

## Flow UI Preview

As promised, we released a preview version of the new UI module based on Vaadin 23. It's called FlowUI and it will allow you to create nice responsive interfaces with easy frontend customization:

![]({{strapiUrl}}/uploads/2022_07_07_flowui_responsive_e0e4018057.gif)

FlowUI will follow the same paradigm as the current UI: server-side programming model, XML layout with visual designer in Studio, data components, similar Java API. But at the same time the set of UI controls and layout rules will be completely different, so please don't expect an effortless migration in the future.

At the moment, the module and its support in Studio are very unstable. We are going to introduce significant and probably breaking changes in subsequent patches of the release 1.3. 

The goal of the current preview is to give community an idea of how the new UI will look, and to start getting feedback on required features and priorities. We hope that by the next feature release in October, 2022, we'll be able to deliver a stable API and a set of minimal functionality for building real applications with the new UI.

## One-Click Cloud Deployment Preview

Another preview feature is the ability to deploy application to AWS EC2 cloud. To see it in action, enable it as described in the <a href="https://docs.jmix.io/jmix/whats-new/index.html#one-click-cloud-deployment" target="_blank">documentation</a>.

![]({{strapiUrl}}/uploads/2022_07_07_aws_deployment_e4b9614a1a.png)

This feature allows you to quickly deploy your application to the cloud. It generates a `docker-compose` file with services based on your application and database settings, creates a virtual machine on AWS EC2, installs Docker on it and builds a Docker image with your application on the VM. Then it runs the containers, gives you the URL, and voila - your application is running in AWS and available to the whole world!

We think that this feature can help a lot when a developer needs to demonstrate the application to clients or colleagues, or just for a simple and lightweight deployment.

## Studio Improvements

We now consider the JPQL designer reliable enough for editing existing queries. It is opened when you click on the query attribute of a data container in the Component Inspector tool window. You can also open the designer for queries defined in code using the gutter icon.

![]({{strapiUrl}}/uploads/2022_07_08_jpql_1_8e5fc51a83.gif)

There are a number of improvements related to Liquibase changelogs: 

- Studio now shows existing Liquibase changelog files in the Jmix tool window under the Data Store node.
- You can create a new empty changelog file using the action of the Jmix tool window and write changesets manually with the help of code completion which suggests names of tables and columns defined in your entities.
- File names of new changelogs now include the timestamp in the HHmmss format (instead of previously added sequential numbers 010, 020, …​). It should eliminate duplication of changelogs when switching VCS branches.

![]({{strapiUrl}}/uploads/2022_07_08_lbcl_1_3938862131.gif)

## BPM Improvements

We have put a lot of effort into improving the BPMN designer in Studio, so now we think it's a good alternative to the runtime designer, offering the tight integration with your source code.

![]({{strapiUrl}}/uploads/2022_07_08_bpm_e5f3355165.gif)

Also, the BPM engine now integrates with the Multitenancy add-on if it is used in the project.

## Role Management

Resource and row-level role management screens now have filters for quick search when editing roles or assigning them to users. Export/import actions allow you to transfer the roles configuration between application instances.

![]({{strapiUrl}}/uploads/2022_07_08_role_filter_7f462b7b5e.png)

Row-level policy editor now offers code completion for JPQL, Check syntax action and link to documentation.

![]({{strapiUrl}}/uploads/2022_07_08_row_level_policy_add36702b0.gif)

## Support for JPA Cascade

As a matter of following standards, we've implemented full support for JPA cascade operations, defined in annotations like `@ManyToOne(cascade = CascadeType.ALL)`. All Jmix features (entity events, dynamic attributes, entity log, security, cross-datastore references) take effect for entities saved through the cascasde operations.

## What's next?

The main direction in the upcoming months is to stabilize FlowUI module, add necessary UI components and build UI for the essential parts of the framework, such as the security subsystem. 

We are also constantly working on fixing issues in the current release 1.3. Patches 1.3.x will be released approximately once a month. 

We'll be glad to see your feedback on our <a href="https://forum.jmix.io" target="_blank">forum</a>!
Thanks to all who contributed with their ideas, suggestions and bugreports! 
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Add-ons and Composite Projects]]></title>
            <link>https://www.jmix.io/blog/add-ons-and-composite-projects</link>
            <guid>https://www.jmix.io/blog/add-ons-and-composite-projects</guid>
            <pubDate>Fri, 27 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/article_eb5f7b50ea.png">The concept of add-ons plays significant role in development with Jmix framework. In this article, we explore what is an add-on and how Jmix Studio helps developing add-ons and modular applications. ]]></description>
            <content:encoded><![CDATA[The concept of add-ons plays significant role in development with Jmix framework. In this article, we explore what is an add-on and how Jmix Studio helps developing add-ons and modular applications. 

An add-on in Jmix is a fancy word for a library, that is a collection of pre-compiled code and other resources that can be used in applications. We use the specific term “add-on” to emphasize that this library, unlike a Java library in general, follows particular rules and leverages some Jmix core features to automatically integrate provided functionality into the host application.  

The most important thing is that an add-on is full-stack: it can contain entities, database schema and UI screens that seamlessly integrate into the data model and UI of the application. So just by adding an add-on as a dependency to `build.gradle`, you can get a whole new subsystem in your project, with data stored in your database and UI integrated with the main menu.  

An add-on doesn’t have to be a complex full-stack project. Many add-ons just provide a UI feature or an alternative implementation of some framework interface like `FileStorage`. In this case, the add-on can just utilize the common infrastructure for publication on <a href="https://www.jmix.io/marketplace/" target="_blank">Marketplace</a> and for easy installation to projects. 

## Developing Add-ons 

Jmix Studio provides the “Single Module Add-on” project template that allows you to quickly bootstrap the development of an add-on. The project will contain a single functional module and a Spring Boot Starter.  

When working on a reusable add-on, you usually have to create also an application which demonstrates use cases for the add-on, and may contain additional automatic tests that are difficult to create in the add-on project itself. 

Studio now offers a feature to streamline the development of such modularized systems. But before looking at it, let’s consider the previous development workflow. 

Generally, the work on an add-on and an application which uses it requires constant switching between two projects. You need to change the add-on's code, build it and publish to the local Maven repository. Then you switch to the application project and IDE loads and reindexes the new add-on artefacts. Now you can adjust the application code, test and run it to see the changes in action. 

![Feedback Loop 1.drawio.svg]({{strapiUrl}}/uploads/Feedback_Loop_1_drawio_bfdcf3761d.svg)

The situation gets worse when you work on an application consisting of multiple add-ons. Most probably, some of your add-ons depend on each other, and you need to switch between several projects and publish multiple add-ons before you can run your application and make sure you got what you wanted. If you failed, you have to repeat the process again. 

![Feedback Loop 2.drawio.svg]({{strapiUrl}}/uploads/Feedback_Loop_2_drawio_36e9edf509.svg)

The feedback loop when developing add-ons was far from ideal: you have to make too many steps to see the result of your changes. The obvious solution would be to combine both the add-on and the runnable application as modules of a single project. On one hand, an IDE then could provide transparent refactoring and you could instantly see the results of changes in any module. On the other hand, the add-ons and applications become tightly coupled for their entire lifecycle, and the idea of an add-on as a standalone library becomes meaningless. 

Wouldn’t it be great if we could work with the add-ons and applications both in separate projects and in a single project when needed? It allows us to keep the codebase clean and manageable, while not sacrificing the short feedback loop when it’s important, especially on the early stages of development when cross-cutting changes are very frequent.  

This is why we improved Jmix Studio to support this scenario with the Gradle’s “composite build”. 

## Composite Projects 

Gradle has several features that help structuring projects, and one of them is <a href="https://docs.gradle.org/current/userguide/composite_builds.html" target="_blank">composite build</a>. It boils down to just using `includeBuild` instruction in the `settings.gradle` file of the composite project: 

```
includeBuild ‘../addon1’ 
includeBuild ‘../addon2’  
includeBuild ‘../myapp’ 
```

In a composite build, Gradle replaces dependencies on artefacts with direct dependencies between subprojects, so changes in an add-on will immediately affect the dependent add-ons and the application. IntelliJ IDEA perfectly imports such a project, taking into account dependencies recognized by Gradle. As a result, you get a composite project which provides the transparent refactoring and removes the need to go through the "publish locally" cycle. 

Jmix Studio supports composite projects starting from version 1.2. It brings to the table a number of features that improve the developer experience even further.  

First of all, you can easily create an empty composite project from a template. Then you can add subprojects by creating new add-ons or applications, checking out an existing project from VCS or just adding an existing folder with a project. 

Studio shows the composite project and all subprojects as top-level nodes in the Jmix tool window: 

![jtw1.png]({{strapiUrl}}/uploads/jtw1_fb9391416f.png)

You can edit common properties of all subprojects: just select **All subprojects** when Studio asks you which project you want to edit: 

 ![edit-properties.png]({{strapiUrl}}/uploads/edit_properties_f19add527a.png)

The common properties include the artifact repository settings and Jmix framework version. So you can upgrade all subprojects to a newer Jmix version at once. 

Probably the most useful feature for large composite projects is the ability to configure dependencies between subprojects in a simple dialog: 

![deps1.png]({{strapiUrl}}/uploads/deps1_655e33a97e.png)

Here **orders** is an add-on which depends on the **staff** and **customers** add-ons. According to changes you make in this dialog, Studio adds artefact dependencies to `build.gradle` files of the subprojects, and also configures the `@JmixModule` annotations of the add-ons. It also prevents you from introducing circular dependencies. In the screenshot below you can see that the dialog doesn’t allow you to make the **customers** add-on dependent on **orders** because **orders** already depends on **customers**: 

![deps2.png]({{strapiUrl}}/uploads/deps2_18c5ae5f9c.png)

When you create new project elements like entities and screens, Studio considers what project is currently selected in the Jmix tool window: 

 ![new-entity.png]({{strapiUrl}}/uploads/new_entity_da72b2d070.png)

The last but not least, Studio correctly hot deploys changes in add-ons to the running application. So if you start the application and then change a UI screen provided by an add-on, you will see the changes in the application without restarting it, as if the screen was in the application’s source code. 

Summing up, it can be said that Gradle’s composite build feature together with IntelliJ IDEA and Jmix Studio support for it allows developers to work with large families of add-ons and applications as with a single multi-module application. At the same time, the developer can detach an add-on at any moment and continue maintaining as a completely separate project. 


]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Definitive Guide to Application Modernization]]></title>
            <link>https://www.jmix.io/blog/application-modernization-guide</link>
            <guid>https://www.jmix.io/blog/application-modernization-guide</guid>
            <pubDate>Mon, 16 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/5674e8_3ff6706b26.png">Legacy applications continue running mission critical business tasks. But when they imminently come to the end of their lifecycle, you need to choose the right option for cost-efficient modernization.]]></description>
            <content:encoded><![CDATA[Legacy applications continue running mission critical business tasks. But when they imminently come to the end of their lifecycle, you need to choose the right option for cost-efficient modernization.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 1.2 Is Released]]></title>
            <link>https://www.jmix.io/blog/jmix-1-2-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-1-2-is-released</guid>
            <pubDate>Mon, 28 Mar 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix1_2_4f6915a8aa.png">In this article, I will briefly describe the most noteworthy features introduced in the new release. ]]></description>
            <content:encoded><![CDATA[A few weeks ago we released Jmix framework and Studio version 1.2. 

In this article, I will briefly describe the most noteworthy features introduced in the new release. You can find more information on the changes, along with upgrade instructions, on the <a href="https://docs.jmix.io/jmix/1.2/whats-new/" target="_blank">What's New page</a> of the documentation.

## New Add-ons
### Business Calendar
<a href="https://docs.jmix.io/jmix/business-calendar" target="_blank">Business Calendar add-on</a> provides API and UI for working with business days and hours. 

Business calendars can be defined at design time using annotated Java interfaces, or at runtime through the application UI. In the latter case, the calendars are stored in the database.

The business calendar API provides methods to check if a given date and time are working hours, and to perform basic arithmetic operations with date and time considering the business hours defined by the calendar.

### Notifications
<a href="https://docs.jmix.io/jmix/notifications/index.html" target="_blank">Notifications add-on</a> enables sending notifications to users via various message channels.

The add-on includes two channels out-of-the-box: the in-app channel shows notifications in the application UI, the email channel sends emails. You can define additional channels in your application.

In-app notifications are displayed to users by a special indicator component that can be placed to any application screen. The indicator shows the number of unread notifications.
When the user clicks on the indicator, the list of notifications is shown. The user can view notifications and mark them as read or unread:

![20220327133229.png]({{strapiUrl}}/uploads/20220327133229_4e4ea2e6ff.png)

The add-on also provides UI to create and send notifications, as well as API to send notifications programmatically in response to any system events.

### Quartz
Jmix uses Quartz job scheduler to run asynchronous tasks. It's a great battle-proven and well known by developers engine, but a minimalistic integration with Quartz lacks some features necessary for many business applications: ability to configure tasks schedule and to start/stop tasks at the application run time. These features are present in the Quartz API, so we have decided to make them available through the Jmix application UI.

![20220327133707.png]({{strapiUrl}}/uploads/20220327133707_c8ddf3403b.png)

The <a href="https://docs.jmix.io/jmix/quartz" taget="_blank">Quartz add-on</a> enables managing Quartz jobs via the application user interface. At design time, a developer defines jobs by implementing the `org.quartz.Job` interface. At runtime, a system administrator can configure the jobs, pause and resume jobs execution, trigger immediate execution of inactive jobs.

The add-on also supports job parameters that can be set in the UI and passed to the jobs.

### Application Settings
Another common requirement for many applications is to have some configuration parameters that can be changed at runtime, without the application restart. Such parameters are often used by business functions and can define various thresholds, coefficients, URLs, etc.

Spring Boot provides a feature called "Configuration Properties", and Jmix uses it extensively for system-level parameters. Unfortunately, this feature is not convenient for working with mutable values, and obviously Spring Boot doesn't provide any integrated UI for managing the values at runtime.

We have considered different approaches, and came to the conclusion that the simplest and most effective way is to use JPA entities as sets of parameters stored in the database. JPA entities are already first-class citizens in Jmix, so settings based on entities automatically acquire a lot of useful features: distributed caching, ability to use all types of the data model, localization of parameter names, access control and audit of changes. Developers can use the entity designer in Studio to create settings classes.

The Application Settings add-on provides a base class for entities and a simple API to load and store a single instance of each settings entity. The client code uses regular entity getters and setters to access parameter values.

When creating a settings entity class, a developer can specify default values for parameters. A default value is returned when the parameter has `null` value in the database.

The add-on also provides a generic UI for managing settings:

![20220327151039.png]({{strapiUrl}}/uploads/20220327151039_4df0304f7b.png)

### OpenID Connect Integration
<a href="https://github.com/jmix-framework/jmix/blob/master/jmix-oidc/README.md" target="_blank">OpenID Connect add-on</a> enables easy integration with OIDC providers (such as Keycloak, Okta, AWS Cognito, etc.) for external authentication and SSO.

In addition to authentication, it allows you to map OIDC claims to Jmix user's roles and attributes. Also, you can configure the add-on to create users in the application database automatically upon first login.

The add-on is now in incubating state, so please be aware that its API and behavior can change significantly in the future.

## Studio Enhancements
### Composite Projects
This is a long awaited feature: ability to develop multiple add-ons and applications in a single IDE project, without the need to publish add-ons for testing them in an application. We have figured out that many big applications are now developed as sets of functional modules located in add-ons, and target applications combine the add-ons in different combinations. A composite project containing all interrelated add-ons and applications greatly speeds up the development of the whole system, and is very helpful at least on the active stage of development. Also, it's very convenient for developing reusable add-ons together with their demo applications.

We leverage the Gradle's <a href="https://docs.gradle.org/current/userguide/composite_builds.html">composite builds</a> feature, when the `settings.gradle` file of the composite project includes subprojects using the `includeBuild` instruction, and Gradle replaces artefact dependencies with direct dependencies between subprojects. 

Studio now fully supports such projects: it can create a composite project and add subprojects, correctly displays subprojects in the Jmix tool window and creates various project elements (entities, screens, etc.) in selected subprojects. It can also change common properties of all subprojects at once. Configuring dependencies between subprojects is on the way and will be included in one of the next Studio patches.

![20220327164940.png]({{strapiUrl}}/uploads/20220327164940_df93c5833e.png)

### Code Snippets
Newcomers often stuck after the initial development stage when the Studio code generation features and visual designers cannot help anymore and programming against the framework API is required. The new code snippets palette allows developers to discover and employ the framework features more easily.

The code snippets palette is displayed on the right side of the IDE when a Java or Kotlin file is opened in the editor. The developer can drag and drop snippets from the palette to code. The snippets are context-dependent and may request parameters from the developer.

![20220327170650.png]({{strapiUrl}}/uploads/20220327170650_aef42b4035.png)

In addition to code snippets provided by the framework, you can define your own snippets in the application or add-on resources: Studio scans for snippets all files named `jmix-code-snippets.xml` in the project classpath. Use examples from the framework modules to write your snippets.

### JPQL Designer
This is another feature that is designed to lower the entry barrier and simplify programming with Jmix.

The JPQL designer allows developers to define JPQL queries for loading entities and scalar values from the database. It is now opened automatically when you use the **Data → Load … by query** code snippets. In the near future, we’ll make it available also for creating and editing queries everywhere in the source code.

![20220327172243.png]({{strapiUrl}}/uploads/20220327172243_287f87cb39.png)

### Jmix Tool Window
As a result of feedback from community, we've improved the representation of UI screens in the Jmix tool window. Now the **User Interface** section shows both screen descriptors and controllers, combined in a node with the screen's ID name:

![20220327174320.png]({{strapiUrl}}/uploads/20220327174320_d3baabdd73.png)

For large projects with lots of entities and screens, we recommend using the new **Group by Packages** mode available in the **Show Options Menu** ("gear" button) of the tool window:

![20220327173855.png]({{strapiUrl}}/uploads/20220327173855_ee3799dd8c.png)

## Conclusion
This article describes the most significant improvements in Jmix 1.2. The full list of changes in the initial release and in all subsequent patches is available in the <a href="https://docs.jmix.io/jmix/whats-new/index.html#changelog">changelog</a> section of the documentation.

Thanks to all who contributed with their ideas, suggestions and bugreports!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix is the new efficient Way of building Business Applications ]]></title>
            <link>https://www.jmix.io/blog/jmix-is-the-new-efficient-way-of-building-business-applications</link>
            <guid>https://www.jmix.io/blog/jmix-is-the-new-efficient-way-of-building-business-applications</guid>
            <pubDate>Tue, 01 Feb 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_Announcement_c56143c579.jpg">Developing business applications could be efficient. Oftentimes it is not. There are a lot of reasons for this, but one of the main ones is developers lack the right tool for the job.  ]]></description>
            <content:encoded><![CDATA[Developing business applications could be efficient. Oftentimes it is not. There are a lot of reasons for this, but one of the main ones is developers lack the right tool for the job.  

Popular libraries and frameworks like Spring Boot (Java), Express JS (Node), React/Angular/Vue (JS) are focusing on technological problems. But they have nothing to do with more specific domain areas: e-commerce websites, line of business applications, or content management systems. They "focus" on all of them, which means they focus on none.  

However, you definitely can be more productive if you find a tool that solves particular problems in a specific area. Such tools do exist. In our case, it’s a tool for creating business applications — Jmix. 

Jmix is a full-stack framework that holds your hand in a lot more situations than you have ever experienced before when writing business applications. 

At first glance, you might think that it’s one of the low-code representatives. Actually, it’s a lot more flexible and gives you the freedom that no low-code platform provides: you fully control every application you develop with Jmix. No charges for end-users, no restrictions on you. Jmix treats your source code as a first-class citizen. It is an open-source “less-code” business application framework from developers for developers.   

Did I get you interested? Let's look into the details.   

## Efficient Application Development   

As I mentioned above, Jmix focuses on a particular area: business applications, and they often have similar characteristics:   

- Fine-grained security capabilities   
- Reporting / Filtering mechanisms for data exploration   
- Big data models   
- A lot of UI screens for administrative tasks or master data   

To address the above-mentioned requirements, the runtime framework needs three things: a good technical foundation, context-aware tooling and ready-made features to solve typical functional requirements. Those three pillars build the basis for efficient business software development:   

1. Integrated full-stack framework   
2. Tooling support   
3. Ready-made features  

Let’s have a look at how Jmix covers those fundamentals.  

## Introducing Jmix   

Jmix is a brand-new framework, which still has the maturity of a platform that is present for more than a decade. It is built on the latest technological underpinnings. Jmix is the ideological successor of CUBA Platform, a framework that is in use by thousands of developers worldwide, from small start-ups to Fortune 500 enterprises. Like CUBA Platform, Jmix aims to create business applications very efficiently, providing solutions to all three pillars of efficient software development. 

![picture]({{strapiUrl}}/uploads/Microsoft_Teams_image_18_c075b00154.png)

Jmix covers all aspects of an application, from the UI or API to the database. It leverages industry standard frameworks and tools to provide the best developer experience. The framework is supported by an IntelliJ IDEA plugin Jmix Studio which helps you get rid of problems connected with multiple tooling and speeds up the development process. 

The focus on business applications allows Jmix to provide solutions almost perfectly fitting the developers’ needs in this area. As I mentioned above, one of the business software development fundamentals is ready-made features. Jmix provides a marketplace of full-stack add-ons to cover everything from the database to the user interface, including: 

- reporting, 
- full-text-search, 
- business process management, 
- enterprise-grade security. 

They can be used immediately without a significant amount of integration work.   

Jmix relies on open-source software and is open-source itself: licensed under Apache 2.0. So, you are not forced into any proprietary technology. 

## Jmix Studio

Being an IntelliJ IDEA plugin, Jmix Studio integrates seamlessly with it and leverages its benefits, such as debugging, test execution, and various ways of source code manipulation that developers need in their daily work. The Studio has a lot of convenient features that enhance your productivity. Based on a visual data model designer, Jmix Studio can scaffold the initial parts of the user interface to adjust the UI later. 

You can switch between the source code and visual representation at any time and make changes both ways. This is true for all artifacts like data models, user interface, business processes, or security role definitions.   

![picture]({{strapiUrl}}/uploads/Microsoft_Teams_image_19_a90a31bef2.png)

Jmix Studio has a free version with the main functionality. For the visual designer productivity enhancements, there are two commercial subscription plans. 

## Jmix Architecture 

For various application aspects, Jmix relies on common frameworks and specifications: 

- Spring Boot underpins Jmix and is used for dependency injection and business logic; 
- JPA for data modeling; 
- Liquibase for database schema definition; 
- Vaadin for user interfaces; 
- Gradle as the build system.  

Let’s dive a bit deeper into these underlying technologies and their roles.  

Spring Boot is the overall basis for Jmix, so developers can easily understand what happens at the Jmix core.  

JPA is a widely used Java specification for accessing data from relational databases. Jmix provides a data access API on top of JPA, incorporating additional aspects like security or soft delete capabilities.  

When it comes to changes and the evolution of the database schema, Liquibase comes into play. Jmix Studio generates the Liquibase changelogs based on your changes in the entity model. Of course, you are free to adjust them however you want if needed. As for the databases, Jmix supports all major relational database systems, like Postgres, MySQL/MariaDB, and commercial products like Oracle and Microsoft SQL Server, out-of-the-box.   

For the user interface, Jmix uses Vaadin by default. Vaadin is a UI framework that focuses on the business applications’ needs and has dedicated UI components. The Vaadin architecture does not require you to write communication APIs between the UI layer and the backend. This reduces boilerplate code. It brings the UI and the backend closer together, which gives you additional benefits like keeping validation logic in one place only or frictionless debugging between the UI and the backend code.  

In Vaadin, you develop the user interface through Java code. This lets you stay in one language for all parts of your application, which makes your development experience more efficient and less cumbersome. 

Jmix enriches the mechanisms of Vaadin with a declarative layout definition, additional UI components, screen abstractions and APIs.    

You can also create a completely custom UI with client-side-based UI frameworks like React or Angular.   

Security is one central piece of Jmix. Why? Because a lot of business software strongly needs it. It comes with very sophisticated security mechanisms, that lets you define the interactions between the data and the users very precisely. It’s a complete role-based access control functionality. But it does not stop there: row-based security requirements like “User Andrew can only see Customers starting with zip-code 9” or “User Andrew is allowed to change Customers’ name, but credit card information is not visible” is easily configurable. The declarative definition either happens at development or runtime by the administrators of the system.   

The data access rules are enforced throughout the system. Jmix UI components respect the currently active security settings on a per-user basis. The same is true when accessing data through the API or programmatically within the application. It prevents you from shooting yourself into the foot when it comes to security. With that, Jmix will never put you into a straitjacket. In case you need to go around the general security mechanisms, there are options for you.   

Jmix switches the toggle to “secure by default” so that you don’t have to think about security in every piece of code you write, following the Secure-by-Design philosophy.   

As you can see, this offering is already quite a bit. But in fact, there is more, covering the ready-made features. But instead of having all functionalities in the framework itself, Jmix allows creating and using add-ons that enhance the capabilities in a modular way.   

## Jmix Add-ons 

Jmix add-ons provide specific solutions to common tasks of business applications. Add-ons are complete solutions, so they differentiate from a library that you need to integrate into your application, writing a lot of integration glue code.    

### BPM

Business applications usually need to model some process specific for the business. BPMN is a standard that provides a solution for this. Jmix BPM add-on extends an application with a BPMN workflow engine built on top of a commonly used Java framework for BPM: Flowable. The add-on integrates Flowable to a Jmix application seamlessly and provides an additional set of features like a process designer, Process Admins UIs and simplified APIs. With those capabilities, the collaboration of multiple people as part of the business process can be easily modeled. 

![picture]({{strapiUrl}}/uploads/Microsoft_Teams_image_20_7681d11b3c.png)

### Reports 

The Reports add-on tackles the creation of reports with various data presented in the application. Reports support various formats like DOCX, XLSX, PDF, HTML, etc. The add-on integrates the reporting engine into a Jmix application with extra features like a report UI wizard and report data fetching from the data model. 

### Search   

Convenient navigating through data is an important aspect of data-centric applications. Jmix offers two solutions. In the core framework, there is an extended Filter UI component, which lets users filter the data by attributes and related entities (and their attributes). 

For unstructured search, Jmix provides a search add-on based on Elasticsearch. Users can search by keywords in a Google search style. The add-on allows you to configure Elasticsearch indexes, automatically sends changed data from the database to the search engine and provides UI components for embedding search into your application UI. Additionally, it seamlessly integrates with the data-access security so that users only see the data they are supposed to see. So once again: it takes away your integration burden.   

### Email   

Jmix comes with multiple add-ons to integrate Email into your application. Send outgoing emails from the application either through the action of a user or programmatically. Receiving emails via IMAP programmatically to trigger further actions is also possible.   

Email integrates with the BPM add-on to combine the power of business process management and user notification.   

### LDAP / SAML

In a lot of businesses, centralized user management is a requirement for applications to integrate with. Jmix supports this with add-ons for LDAP and SAML for single-sign-on (available in February 2022). The existing user management within Jmix automatically adapts to the external user management system when the add-ons are used.   

### API  

Integrating with other systems is crucial for every modern application. With the Spring Boot base, you can of course build a complete custom API for external applications through various protocols. Also, two add-ons automatically expose data and functionality through common approaches: REST API and GraphQL (available in February 2022). Integration with data-access security is baked in by default.   

Those were the most frequently used add-ons. There are various others, by the Jmix core team or by the community, that solve dedicated problems like audit logs, translations, maps or dynamic attributes. Jmix Studio comes with an add-on marketplace as an easy way to explore and install an add-on with a few clicks. 

## Summary   

Jmix is a specialized tool for creating business applications. Through the focus on the problem domain, it reduces friction and speeds you up.  

Jmix covers the essentials of efficient software development with an integrated full-stack framework on top of the Java ecosystem, developer tooling support and add-ons with solutions to common tasks.   

Due to its modular and open architecture, the framework is very flexible. You can extend or change the core functionalities in almost any way. Jmix has a growing community and active development in the core framework and add-ons ecosystem.   

Efficient software development leads to faster feedback cycles, which leads to more interaction with your users and therefore to better solutions for your business. And that is what we all want, right?   

If this sounds promising to you and you want to learn more, jump over to the Quickstart or try it out on your own. There is also an open community waiting for you, so don’t hesitate to ask any questions. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 2021 Recap and 2022 Roadmap ]]></title>
            <link>https://www.jmix.io/blog/jmix-2021-recap-and-2022-roadmap</link>
            <guid>https://www.jmix.io/blog/jmix-2021-recap-and-2022-roadmap</guid>
            <pubDate>Wed, 29 Dec 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/BLOG_Novyj_god_775267efab.png">One more year is almost gone, so it’s time for the traditional recap of what the team was working on and what we plan for the upcoming year.  ]]></description>
            <content:encoded><![CDATA[One more year is almost gone, so it’s time for the traditional recap of what the team was working on and what we plan for the upcoming year.  

## 2021 

2021 turned out to be super busy, with extensive R&D and multiple new features in development. We have grown to over 60 to support all these activities. The adaptation of new members put high pressure on the rest of the team in the first half of the year, but proved worth it – now we are capable to undertake much more than we could imagine a year ago. 

The most important task was releasing a stable version of Jmix. <a href="https://jmix.io/blog/jmix-1-0-is-released/" target="_blank">Version 1.0</a> was released in June, though to be honest I think we can only consider this task complete since the <a href="https://jmix.io/blog/jmix-1-1-is-released/" target="_blank">recently released v. 1.1.</a> It brought multiple usability and stability improvements, and most of CUBA Add-ons supported by Haulmont were ported to Jmix.  

We understand that enterprise projects are long-living, so facilitating migration to the latest version of the framework has always been our priority. In Jmix 1.1 we implemented <a href="https://docs.jmix.io/jmix/cuba/index.html" target="_blank">a special compatibility module and Studio support</a> for easy migration from its predecessor CUBA Platform. We hope to see more CUBA projects converted to Jmix soon.  

This year also gave birth to a new product – an IntelliJ IDEA plugin <a href="https://plugins.jetbrains.com/plugin/15075-jpa-buddy" target="_blank">JPA Buddy.</a> In very simple words, we used the experience of working with data model in Jmix, and adapted it to generic Java and Kotlin projects using JPA. The success was beyond any expectations – over half a million unique downloads in a year! This proved that our ideas, presented as lightweight, non-invasive tools are appreciated by broad developer community. You are welcome to learn more in JPA Buddy’s <a href="https://www.jpa-buddy.com/blog/the-first-annual-recap-from-jpa-buddy/" target="_blank">recap article</a>.  

![logo jpa buddy]({{strapiUrl}}/uploads/Logo_JPA_Buddy_1b97eec30f.png)

You might think that JPA Buddy is irrelevant to Jmix community, however it brought an interesting side effect.  Such a small and widely popular tool has very fast feedback and release cycles. This in turn results in a very polished product with great developer experience. And we copy many of JPA Buddy ideas and features back to Jmix! For example, this is how we moved from custom DB migration scripts to industry-standard Liquibase.  

One major feature that we started is CloudControl, a project which extends Jmix with DevOps and cloud deployment capabilities. When it is rolled out, Jmix will support the full SDLC (software development lifecycle) of an application. CloudControl will support two scenarios:  

- one-click deployment from Studio directly to a public cloud like AWS, which is ideal for prototypes, one-man projects or demos;  
- a complete infrastructure and collaborative environment for managing and deploying your projects without the need for deep DevOps knowledge.  

Let me elaborate on the last point. Inline with our “do not reinvent the wheel” mantra, CloudControl relies on GitLab under the hood, and it can either procure you a fully configured instance, or connect to your current one. So, you get a ready-to-use issue tracker, CI/CD engine, git and binary artifacts repositories. On top of that CloudControl adds:  

- Code generation and drag & drop designers for Terraform, Docker Compose and Kubernetes, so you can easily describe the desired project infrastructure.   
- Procurement and management of environments for your project in a public cloud or a private Kubernetes instance 
- Code generation for standard CI/CD pipelines 
- Governance policies for access to projects and environments 
- Simplified and focused web interface, integrated with Jmix Studio  

In essence, CloudControl is a bridge between development tools, DevOps infrastructure, and environments.  

Another key direction of our work has been the new front-end technologies. Initially, we planned that the new React client would be a 1:1 alternative for Vaadin over generic GraphQL API. However, as we progressed with R&D, we realized that support for two equal UI clients turns Jmix into a mess: double documentation, different APIs, etc. Moreover, Jmix’s generic API approach encountered reservations among web developers, who are used to working with dedicated endpoints.   

The above made us reconsider our strategy. Jmix will retain Vaadin as the primary client and focus on seamless, pure Java/Kotlin full-stack development. In addition, Jmix Studio will automate generating custom REST/Graph QL endpoints (in addition to the generic API) to facilitate using a Jmix application as a backend. With this in mind, we started work on upgrading to the latest Vaadin 23 LTS release. 

However, the work we did on the React client is not lost. Recently, we released a beta version of <a href="https://plugins.jetbrains.com/plugin/17467-react-buddy" target="_blank">React Buddy</a> – an IntelliJ IDEA/WebStorm plugin providing visual tools and coding assistance to React developers. Like with JPA Buddy, we hope that it will become widely popular and benefit the Jmix community. React Buddy can offer RAD experience for a React UI client over Jmix GraphQL endpoints with some additional work currently in progress. And being a separate product, it will not clutter the Jmix codebase. 

![logo React Buddy]({{strapiUrl}}/uploads/Logo_React_Buddy_a2e1766bdf.png)

As planned, we started R&D on the Flutter mobile client on the back of the same GraphQL API. Other smaller directions included such Jmix improvements as JPQL designer, support for code snippets, and a BPM designer in Studio. All of these are well on the way and look promising. Perhaps the only planned feature that we did not even start due to the lack of resources was support for design-time reports. 

Finally, in December we launched the new website. It was the first step in realigning our marketing strategy. We see that Jmix’s ease of use and high productivity resonate first of all among those who care about the business result: technical managers, freelancers, members of small IT agencies. So now we talk more about business values and position Jmix as a healthy alternative to the overhyped Low Code platforms: flexible, open-source, developer-friendly, and without crazy runtime fees.  

Together with the new product features, we hope that it will help us ramp up sales and see faster community growth. By the way, this year we have grown by over 20% with almost zero marketing activities – which backs our confidence.  

I want to finish off 2021 with a massive “thank you” to all our community members for understanding the reasons behind the recent price change. Your support is greatly appreciated and will help us build a better product and professionally maintain it in the future.  

## 2022

As you can see, we started multiple new directions this year. We made good progress, but most required extensive R&D work, and we did not even expect to finish them in one year. So for 2022, the ultimate goal is to complete this work.  

Here is a high-level release plan for the key features, and you can also track the live roadmap <a href="https://github.com/orgs/Haulmont/projects/1" target="_blank">here</a>. 

- Q1. JPQL designer, BPM designer, Business Calendar, and User Notifications Add-ons 
- Q2. Preview versions of CloudControl and the new Vaadin 23 UI client  
- Q3. Stable versions of CloudControl and the new Vaadin 23 UI client  

As discussed above, we keep working on making Jmix and React Buddy work together to offer faster React front-end development for your Jmix applications. I am confident that we can release something this year. Flutter work has been put on hold as we first focus on finalizing other projects.  

Of course, we also plan to release many other improvements and a few Add-ons this year. We also have one more major development direction, which I will keep secret and announce later in the upcoming year. Stay tuned!  

I hope that you will enjoy what’s coming for Jmix in 2022. Our team wishes you a great New Year and many successful projects. Thank you all for staying with us! Your ideas and suggestions are always welcome as comments in this <a href="https://forum.jmix.io/t/jmix-2021-recap-and-2022-roadmap/919" target="_blank">post</a>. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 1.1 is released!]]></title>
            <link>https://www.jmix.io/blog/jmix-1-1-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-1-1-is-released</guid>
            <pubDate>Mon, 01 Nov 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/small_Jmix1_1_770a06b49a_4960811a48.png">The next version of Jmix – 1.1 - is available for download. 
In this version, we introduce several major features:

1.	Migration from CUBA projects
2.	Kotlin support
3.	Full Java 17 support

Jmix Studio was updated too to support all these features.]]></description>
            <content:encoded><![CDATA[The next version of Jmix – 1.1 - is available for download. 
In this version, we introduce several major features:

1.	Migration from CUBA projects
2.	Kotlin support
3.	Full Java 17 support

Jmix Studio was updated too to support all these features.

## CUBA projects migration

You can migrate a CUBA project to Jmix, there are two ways to do it.

If you open CUBA project in Jmix Studio, the IDE will ask you if you want to migrate to the latest Jmix version, so you can start the process instantly. 
<br>
<img src='{{strapiUrl}}/uploads/1_a69e931d8e.png'>
 
But if you want to start the migration later, you can do it using Jmix Studio’s menu: `File -> New -> Jmix project from this CUBA project`.
<br>
<img src='{{strapiUrl}}/uploads/Screenshot_2021_10_30_at_10_36_55_2fd61a90e4.png'> 
 
Studio automatically changes the project structure to satisfy Jmix requirements. Most of the code remains untouched, Jmix uses CUBA Compatibility API to provide backward compatibility after migration.

Migration results and recommendations log are stored in the `MigrationResult.md ` file. It contains automatic migration results and recommendations on manual operations. 
Please note that the migration procedure keeps your CUBA project untouched, so it’s safe to run the procedure on any working copy of a project.

You can find more details in <a href="https://docs.jmix.io/jmix/cuba/index.html" target="_blank">Jmix Documentation</a>.

## Kotlin Support

With Jmix 1.1, we provide the application template for Kotlin developers as well as full Kotlin support in Jmix Studio.
<br>
<img src='{{strapiUrl}}/uploads/Screenshot_2021_10_30_at_10_39_35_8400b34f25.png'>
 
If you choose the Kotlin-based project template, Jmix Studio will generate entities, services and screen controllers using this language and its best practices. Please note: when developing JPA entities with Kotlin, you need to remember some rules in order to avoid issues in runtime: use open classes, implement `toString()` method in a special way, etc. 

There is <a href="https://www.jpa-buddy.com/blog/best-practices-and-common-pitfalls/" target="_blank">an article</a> about best practices and common pitfalls in Kotlin. The good thing Is that visual editors in Jmix Studio take all these issues into account, so you don’t need to remember them.  

The same applies to all generators and code intentions in the IDE to help both new and experienced Kotlin developers make their code better.

## Java 17 support

Jmix 1.1 now allows you to use Java 17 in your project code. The framework runtime was fully tested against the 17th version of the JDK. It is the LTS (long-term support) version, that is <a href="https://mreinhold.org/blog/forward-even-faster" target="_blank">supported for two years</a>. It means the stable platform for running Jmix applications and proper support level from JDK vendors for this time. 
Apart from that, Java 17 provides a lot of improvements that allow applications run faster (thanks to compiler optimizations and better GCs) and developers to write better and safer code (sealed classes, records, switch expressions, etc.).

If you want to use Java 17 in your project, just ensure that you removed `sourceCompatibility` line from your `build.gradle` project and you installed Gradle 7.2 or later as your build tool, you can set it in `gradle-wrapper.properties`. 
<br>
<img src='{{strapiUrl}}/uploads/Screenshot_2021_10_30_at_10_42_27_d708bbcd65.png'>
 
Of course, you need to set up JDK 17 support in Jmix Studio settings.
<br>
<img src='{{strapiUrl}}/uploads/Screenshot_2021_10_30_at_10_46_41_8460b0854f.png'>
 
After that, you can enjoy the latest Java with Jmix. 

## Studio Improvements

Let’s go through the most noticeable Jmix Studio improvements.

*New “Inject” Dialog* now shows object available to injection to the following categories to provide better observability:

- Project Beans - Spring beans of the current project
- Project Properties - configuration property classes of the current project
- Infrastructure - frequently used framework beans
- Other Beans - all other Spring beans of the framework and add-ons
- Other Properties - all configuration property classes of the framework and add-ons

<img src='{{strapiUrl}}/uploads/Screenshot_2021_10_30_at_20_20_03_2584c1a829.png'>

In addition to this, you can always use quick filter: just start typing the desired component name to reduce a number of available objects.
*New Visual Components* include ResponsiveGridLayout, Single- and Multi- Select Lists.

ResponsiveGridLayout is a container where the components are laid out on a grid, based on Bootstrap’s 12 columns grid system. Let’s have a look at the following code:

```
<window xmlns="http://jmix.io/schema/ui/window">
    <layout>
        <responsiveGridLayout stylename="demo">
            <row>
                <col>
                    <label value="1 of 2"/>
                </col>
                <col>
                    <label value="2 of 2"/>
                </col>
            </row>
            <row>
                <col>
                    <label value="1 of 3"/>
                </col>
                <col>
                    <label value="2 of 3"/>
                </col>
                <col>
                    <label value="3 of 3"/>
                </col>
            </row>
        </responsiveGridLayout>
    </layout>
</window>
```
This code will be rendered into the following UI:
<br>
<img src='{{strapiUrl}}/uploads/Screenshot_2021_10_30_at_20_26_05_3cfdf0ca74.png'>
 
As you can see, now you have more options for planning your layout.

*Select List* displays a pre-defined list of options in a vertically scrollable list. SingleSelectList allows users to select only a single item from the list. MultiSelectList allows multi selection, obviously.
<br>
<img src='{{strapiUrl}}/uploads/Dizajn_bez_nazvaniya_d57348fd8f.jpg'>
               
*BPM Designer* now allows developer to create BPM diagrams right in the Studio, if they have BPM add-on installed. It simplifies BPM process deployment, you don’t need to unload it from the development environment and import into production. Now BPM process descriptors and related code (services, user providers, etc.) are stored in the codebase and there is no chance to deploy a new process version to an old application.
<br>
<img src='{{strapiUrl}}/uploads/Screenshot_2021_10_30_at_20_07_20_88aa300fe9.png'>
 
Please note that BPM designer is still available in Jmix application, so you can create ad-hoc business processes like you did in Jmix 1.0.

## Conclusion

We continue improving both Jmix framework and Studio. With new functionality you can start migrating your CUBA applications to the modern application stack: Jmix (with Spring Boot at its core) and JDK 17. And if you want to evaluate Kotlin for backend development, now is the time. You can find more information about Jmix 1.1 in the <a href="https://docs.jmix.io/jmix/whats-new/index.html" target="_blank">release notes</a>.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix Search Add-On - Simplifying Elastic Search]]></title>
            <link>https://www.jmix.io/blog/jmix-search-add-on</link>
            <guid>https://www.jmix.io/blog/jmix-search-add-on</guid>
            <pubDate>Wed, 14 Jul 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Kartinka_dlya_stati_po_Jmix_Search_5e23ac9b31.png">Good search capabilities are always useful in any application which works with data.]]></description>
            <content:encoded><![CDATA[## Introduction 

Good search capabilities are always useful in any application which works with data. In CUBA, there was an add-on - “FTS” based on <a href="https://lucene.apache.org/" target="_blank">Lucene</a>. For Jmix, we have re-implemented the search engine. Now we use <a href="https://www.elastic.co/" target="_blank">Elasticsearch</a> as the search engine. 

Elasticsearch is based on Lucene and uses the same abstractions - docs and indexes. Since Jmix is a framework for data-centric applications, we need to create documents and build indexes based on data stored in a relational database.
 
In this article we will discuss approaches for Elasticsearch usage in Spring Boot and ideas that were implemented in Spring Boot-based Jmix framework. 

## Spring Boot Solution

Spring Boot supports Elasticsearch, there is a <a href="https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/" target="_blank">separate project</a> for it. 

To add Elasticsearch to our Spring Boot application, we need to define “Documents” as Java classes similar to JPA Entities. Let’s have a look at the example from the Spring documentation:

```java
@Document(indexName="books")
class Book {
    @Id
    private String id;

    @Field(type = FieldType.text)
    private String name;

    @Field(type = FieldType.text)
    private String summary;

    @Field(type = FieldType.Integer)
    private Integer price;

	// getter/setter ...
}
```  

Here we define an indexed document, its fields and index name. In order to work with indexes, save documents and perform search, we need to create a Spring Data repository similar to this:

```java
interface BookRepository extends Repository<Book, String> {
  List<Book> findByNameAndPrice(String name, Integer price);
}
``` 

The Spring Boot API for Elasticsearch is slick and familiar for developers, but if you want to perform a search in the database, things become a bit more interesting. If we want to do that, we need to implement the following code.

For the index creation:
1. Define documents with ID field and table name to link them to data
2. When data is stored or updated, create a document, by copying changed data from the updated data rows
3. Send this document to the Elasticsearch

For the search:
1. Find a document according to search query
2. Find a corresponding entity by the table name and ID

This is not hard work, but it still requires some manual coding. So, is there a way to simplify it a bit? 

## Jmix Solution

In Jmix, we provide a simple way for <a href="https://docs.jmix.io/jmix/search/index-definitions.html" target="_blank">configuring Elasticsearch indexing</a>. It will look familiar for developers who worked with BPM or Security in CUBA, and this approach won’t look strange for the experienced Spring Boot developers. Let’s have a look at the index configuration for the Book JPA entity.

```java
@Table(name = "book")
@Entity
public class Book {

    @Id
    private UUID id;

    private String name;

    private String summary;

    private Integer price;


    // getter/setter ...
}

```

If we want to define an index to search books using Elasticsearch, we just need to define an interface and define one method:

```java
@JmixEntitySearchIndex(entity = Book.class)
public interface BookIndexDefinition {
	@AutoMappedField(includeProperties = {"name", "summary", "price"})
	void bookMapping();
}
```
After that, the index will be created automatically at the boot-time. There are various options for index creation: you can use masks to include or exclude entity fields to/from indexes, you can include referenced entities, index uploaded files, etc. You can find more details about it in the add-on documentation

OK, the index is created, now we need to populate it. In Jmix, we set up a queue to store entity changes and an entity tracking listener. The listener tracks changes in an entity’s fields which are included into indexes and adds those changes into the queue. The third component - quartz job that updates Elasticsearch indexes. 

The detailed search architecture diagram is below:


![search_architecture.png]({{strapiUrl}}/uploads/search_architecture_5f06326fa4.png)

So, Jmix framework creates and updates indexes automatically. After that, we can use the EntitySearcher service that will send a query to Elasticsearch, receive results, and return corresponding entities.  

Jmix search add-on is easy to set up and use, but it has some limitations: it does not allow native Elasticsearch queries, therefore, it is less flexible. So, if this functionality is required, you can add Spring Boot Elasticsearch library and use its API to execute arbitrary queries. 


### Using Search in the Backoffice UI

The Jmix framework provides a component that allows to perform search from the backoffice UI. Basically it is one text field similar to what we usually see in search engine web pages like google or duckduckgo, and it provides pretty advanced functionality. 

![search.png]({{strapiUrl}}/uploads/Search_UI_143fd48910.png)

In the screen descriptor it is represented by one tag:

```xml
<search:searchField id="bookSearchField" entities="Book"/>
```
So, this component will initiate search through all books added to the index. For example, if we have the following data set:

![Books.png]({{strapiUrl}}/uploads/Books_bf65243c2e.png)

And start searching for the “jungle” word, the search component will open the screen which displays all books which fields contain the word. 

![Search_Result.png]({{strapiUrl}}/uploads/Search_Result_9a698fe156.png)

By clicking on an entity name, we will open the editor screen for the selected entity. 

In addition to this, we can add full-text search capabilities to the generic filter. Apart from JPQL, Property and Group conditions, we can see the “Full-text condition” option. If we choose this condition, we can select a search strategy and apply it for the search string.

![condition_editor.png]({{strapiUrl}}/uploads/condition_editor_dbe15d92d1.png)

## Conclusion

In Jmix, we keep the approach used in the previous versions: take a battle-proven framework, build an API over it and simplify usage as much as it needs to be and we don't hide implementation from a developer, from the other side. 

With Jmix you can build full text search indexes for your database quickly and easily. All you need to do - define interfaces and add annotations to their methods. Automatic index data queuing and quartz jobs will do the rest. And now you can use not only Jmix’s APIs to search data, but any tool that works with Elasticsearch compatible engines as well as Jmix’s Backoffice UI.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 1.0]]></title>
            <link>https://www.jmix.io/blog/jmix-1-0</link>
            <guid>https://www.jmix.io/blog/jmix-1-0</guid>
            <pubDate>Tue, 13 Jul 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_1_0_92b187423c.png">“CUBA” becomes “Jmix”! It is a big rebranding, but it is worth all the effort. This name is much simpler to explain: “J” for “Java” and “mix” for the technologies and frameworks mixed in one application.]]></description>
            <content:encoded><![CDATA[
“CUBA” becomes “Jmix”! It is a big rebranding, but it is worth all the effort. This name is much simpler to explain: “J” for “Java” and “mix” for the technologies and frameworks mixed in one application.

Effectively Jmix is the next major CUBA version with well-known APIs and development approach. And it is still the same set of convenient tools and code generators. 

With Jmix, we try to achieve the following goals:

1. Better developer’s experience. Modern frameworks are simple to use, easy to configure and provide a big library ecosystem.
2. Re-use existing solutions as much as possible. Do not reinvent the wheel.
3. Smaller app footprint, only functionality which is absolutely necessary should be in core.
4. Powerful tools - keep great experience and development speed.

Let’s have a look at the framework and things that we’ve implemented to achieve those goals. 

## Core

The most noticeable change: Jmix is based on the latest stable Spring Boot framework version instead of “pure” Spring. Using Spring Boot gives us the following advantages:

1. Familiar experience. Currently almost every Java developer has experience working with Spring Boot. With Jmix, Spring Boot development skills can be used at its full, no need to learn a new framework.
2. Jmix relies on existing infrastructure with huge community support and a tremendous documentation base. In Jmix we got rid of many features that were implemented in the previous version in favour of the “standard” libraries.
3. Simplified deployment, including great containerization support, out-of-the box. In the simplest case, you don’t even need to create a Dockerfile to create an image for your application.  

In Jmix, we continue to move all “optional” functionality to add-ons. An “empty” Jmix application contains less functionality “out-of-the-box” than a CUBA application. 

Even data access services and security management - are in the separate modules in Jmix. But those add-ons are included by default when you create an application in Jmix Studio. Let’s have a closer look at those modules.

### Data Access Layer

Data Access Layer is a cornerstone of any data-centric application, and we took the best parts of it from the CUBA framework: optimistic locking functionality, soft deletion, cross-datastore references, etc.  

With all the advantages, CUBA data model has one fundamental flaw: it is pretty rigid. For example, if you needed soft delete, you had to implement a proper interface (or inherit your entity from `BaseEntity`) and introduce columns with predefined names in the corresponding table. All primary keys had to be stored in the column with the `id` name if you used the `StandardEntity` class.

In Jmix, the Entity model becomes more flexible.  We decided to deprecate interfaces that specify entity functionality. They are replaced with common annotations. 

All you need to do - add the annotation `@JmixEntity` to a class to make it accessible to the framework. We ditched some custom interfaces, you should use JPA’s `@Version` annotation and Spring Boot’s `@CreatedBy` instead of proprietary `Versioned` and `Creatable` interfaces. 

This allows us to make code more explicit - you can tell which features are supported by the entity by just looking at its code.

```
@JmixEntity
@Table(name = "CONTACT")
@Entity(name = "Contact")
public class Contact {

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "ID", nullable = false)
   private Long id;

   @Version
   @Column(name = "VERSION", nullable = false)
   private Integer version;

   @InstanceName
   @NotNull
   @Column(name = "NAME", nullable = false, unique = true)
   private String name;

   @LastModifiedBy
   @Column(name = "LAST_MODIFIED_BY")
   private String lastModifiedBy;

   @Temporal(TemporalType.TIMESTAMP)
   @LastModifiedDate
   @Column(name = "LAST_MODIFIED_DATE")
   private Date lastModifiedDate;

```

Another renaming - “CUBA Views” are now “Fetch Plans”. The new name describes the purpose of these artifacts much better. Functionality stays the same though with one exception: Jmix’s data access layer now supports automatic lazy loading of references. 

So if you choose not to use fetch plans for filtering out local attributes, you will never get the notorious “UnfetchedAttributeException” anymore.

In Jmix 1.0, we introduce a new experimental feature  - Spring Data repositories support. Now in Jmix you can define data repositories using the well-known approach from Spring: repository interfaces. The concept was described in the <a href="https://www.cuba-platform.com/blog/spring-query-interfaces-in-cuba/" target="_blank">blog article</a>, now this feature is implemented in Jmix. We’re creating a developer’s guide for this feature now, but you still can try it in this release simply by creating a Spring Data interface for data manipulation.

```java
public interface PetRepository extends JmixDataRepository<Pet, UUID> {

    List<Pet> findPetsByName(String name);

}
```

Another big thing that should be mentioned is the database generation and update process. We decided to use Liquibase instead of the custom DB update engine. Spring Boot is responsible for running these scripts. 

Liquibase can generate DB-agnostic update scripts, so if you develop a product or an add-on with Jmix, you won’t need to generate database creation scripts for all possible RDBMSes. Liquibase will use the appropriate SQL dialect depending on a JDBC driver. 

### Security

The Jmix security engine is built as a very thin layer over Spring Security. The data model has changed accordingly - in Jmix we use classes from Spring Security like UserDetails and SessionRegistry, so it might look a bit unfamiliar for seasoned CUBA developers at the beginning.

Roles have changed,  “Resource Roles” and “Row-level Roles” have replaced “Roles” and “Access Groups”. In addition to this, we’ve added an “Aggregation Role”. This is a role that is composed from other roles - there were a lot of requests from users about this feature. 

Spring security is not the easiest thing to set up but in Jmix we made this process as seamless as possible. You will be able to set access to entities, attributes, screens, as well as set up row-based security as it was in CUBA.

## User Interface

Backoffice UI (a.k.a. Generic UI) stays intact. Component-based UI was a big part of CUBA and we will support it in Jmix. Support includes screen generators, UI editors in the IDE, etc. In Jmix, we have added new components like a separate Pagination component and ResponsiveGridLayout. 

Please note that Jmix applications are single-tiered; there is no more “core-web” separation. This approach is simpler and fits into the modern architectural approach. If you want a separation, you can achieve it by implementing two Jmix applications: front-end with Backoffice UI and back-end that exposes an API. In this case, the UI won’t depend on the data model and you will pass DTOs to display data on the front-end or process it on the back-end.

## Jmix Studio

With new Jmix Studio, you can choose one of the four templates for your project:
- `Single Module Application` - to create a “regular” Jmix application. 
- `Theme Add-On` - to create a CSS theme for your application. A theme can be installed as an add-on.
- `Widget Add-On` - this project type simplifies a custom widget creation.  
- `Single Module Add-On` - the generated project structure will contain all settings specific for Jmix add-ons and a sample code: an entity, its UI screen and integration tests.

The next big thing is project navigator redesign. To assist with project development, the Studio provides a <a href="https://docs.jmix.io/jmix/latest/studio/tool-window.html" target="_blank">separate tool window</a>. With this window, you shouldn’t choose between Jmix project structure and source code anymore. 

![RestApi.png]({{strapiUrl}}/uploads/image_1c4a19ea4d.png)

Jmix project structure navigator can help with viewing configuration files, navigate through the data model, configure data stores, and many other things.

If you are a BPM add-on user, you will be able to create BPM diagrams in the design-time (beta feature). All business processes are deployed on the application start-up. 


![RestApi.png]({{strapiUrl}}/uploads/bpmn_idea_c107e47b25.png)

## Add-ons

With Spring Boot, it is simpler to implement add-ons for the Jmix framework. Basically, those are Spring Boot starters. 

On the one hand, it allows us to use almost all Spring Boot libraries, which is a great thing. On the other hand, in CUBA there were add-ons that implemented business functionality (e.g. Reports, Charts, etc.) in contrast to Spring Boot libraries most of which implement “system” functionality: database access, security, messages handling, you name it. 

So we’ve reimplemented a lot of CUBA add-ons for Jmix to deliver a familiar set of features to the existing CUBA developers and to extend horizons for the Jmix newcomers. 

Almost all Jmix add-ons now contain two modules that can be installed separately: program logic and UI. So, if you need good old CUBA’s Entity Log feature, but want to fetch entity changes via REST API, you can install this add-on without UI. 

In <a href="https://www.jmix.io/marketplace/" target="_blank">Jmix marketplace</a> you can find about 20 add-ons including Reports, Charts, Maps and BPM. 

## Deploy

Jmix uses Spring Boot build plugins for application deployment. It means that you can run a Jmix app as an executable fat JAR or deployable WAR (it also can be executed as a standalone application). 

Containerization is supported in Spring Boot “by default”. To create an application image, you don’t need to create a `Dockerfile`. In the simplest case, issuing `gradlew bootBuildImage` command should be enough to have a Docker image created and uploaded to an image repository. 

For cloud environments, any Jmix application is “just another Spring Boot App”, so all deployment manuals can be applied for Jmix. 

## Migration from CUBA to Jmix

First thing: we are not going to abandon CUBA. Version 7.2 is going to be long-term-supported and will be supported for five years. And after that, there will be commercial support available for the next five years. So, CUBA framework will live for at least next 10 years.

Migration functionality is being developed to provide as slick a process as possible in Jmix Studio. If you are eager to migrate from CUBA now, you’ll need to do it manually. We plan to deliver automated migration to Jmix in version 1.1 by the end of the year. 

For backward compatibility purposes, you can use the `jmix-cuba` module. This module contains most of the APIs implemented in CUBA. So, you won’t need to change your code much in order to migrate to the next framework version. 

## Conclusion

Jmix is the next big step in CUBA Platform evolution. With Jmix 1.0 you can start implementing your applications using all new add-ons and visual designers that we provide you. 

Now you can enjoy almost all Spring Boot starters and use techniques applicable for the most popular Java framework in the world. At the same time you still have all the convenient and familiar APIs and functionality provided by Jmix - a CUBA descendant as well as great development experience with the new Studio.




]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix 1.0 is Released!]]></title>
            <link>https://www.jmix.io/blog/jmix-1-0-is-released</link>
            <guid>https://www.jmix.io/blog/jmix-1-0-is-released</guid>
            <pubDate>Wed, 07 Jul 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Jmix_1_0_92b187423c.png">We have released a stable version - 1.0 of the Jmix framework. We’ve spent most efforts on bugfixes and code stabilization to deliver the production-ready framework. But that is not all. ]]></description>
            <content:encoded><![CDATA[Finally, we have released a stable version - 1.0 of the Jmix framework. After [version 0.9 release](https://www.jmix.io/blog/announcing-jmix-0.9-pre-release-version/) we’ve spent most efforts on bugfixes and code stabilization to deliver the production-ready framework. But that is not all. Jmix is evolving and we’ve added some new features that should simplify application development even more.

## Jmix Studio

In addition to the existing Jmix project templates, we have added one more: `Single Module Add-On`. The generated project structure will contain all settings specific for Jmix add-ons and a sample code: an entity, its UI screen, and integration tests. This should help you to ramp up your add-on development project faster.

If you are a BPM add-on user, you will be able to create BPM diagrams in the design time now (beta feature). All business processes should be deployed on the application start-up. 

![bpmn_idea.png]({{strapiUrl}}/uploads/bpmn_idea_c107e47b25.png)


## Core

We haven’t changed Jmix’s core much since release 0.9, but there is a feature that should be mentioned. 

A new experimental feature - Spring Data repositories support. Now in Jmix, you can define data repositories using the well-known approach from Spring: repository interfaces. The concept was described in the [blog article](https://www.cuba-platform.com/blog/spring-query-interfaces-in-cuba/), now this feature is introduced in Jmix. We’re creating a developer’s guide for this feature now, but you can try it in this release.

## Add-Ons

Now you can find more add-ons in the Jmix marketplace. The most significant are:

* Audit
* BPM
* IMAP
* Charts & Pivot Table
* AWS File Storage
* UI Localization: German, Chinese, Russian
* Multitenancy
* Reports
* Search

All of them are ready for 1.0 and can be installed from the Jmix Studio. 

The last one - Search - should be mentioned separately. In Jmix this add-on uses the Elasticsearch engine. Also, we have introduced a new configuration approach for the full-text-search feature, you can find more information about it in the <a href="https://docs.jmix.io/jmix/latest/search/index.html" target="_blank">documentation</a>.

## Conclusion

Jmix is ready for production. If you have started development with Jmix 0.9, you can find a migration guide in <a href="https://docs.jmix.io/jmix/latest/whats-new/#upgrade-from-0.9" target="_blank">the documentation</a>. 

In the next step, we are planning to have support for the migration of existing CUBA apps to Jmix with the help of Jmix Studio. This functionality is being developed to provide as slick a process as possible.

Anyway, with Jmix 1.0 you can start implementing your applications using all-new add-ons and visual designers that we provide you in this version. 

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Database Lifecycle in Jmix: Migration Challenges]]></title>
            <link>https://www.jmix.io/blog/database-lifecycle-in-jmix-migration-challenges</link>
            <guid>https://www.jmix.io/blog/database-lifecycle-in-jmix-migration-challenges</guid>
            <pubDate>Wed, 30 Jun 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/blog_img_1_877d7c8779.png">In Jmix, the JPA data model, hence database is a cornerstone of the application.]]></description>
            <content:encoded><![CDATA[## Introduction

In Jmix, the JPA data model, hence database is a cornerstone of the application.

In the case of software development, the principle “if it works, don’t touch it” does not always work. Software changes are inevitable, database migrations too. And if database update goes wrong, you can lose data - one of the most valuable things for the business.

In our framework we use JPA over relational databases. Nowadays RDBMS are widely used in enterprise applications. Two key things that provide this success are: data consistency (it is very important in many business areas) and advanced ORM frameworks like Hibernate or EclipseLink that simplify application development. 

Relational DB update is a complex process, we need to keep data consistent after migration is over and sometimes it is not as easy as it seems.

In the <a href="https://www.jmix.io/blog/database-lifecycle-in-jmix/" target="_blank">previous article</a> we’ve made an overview of the database migration process in Jmix. In this article we’ll have a look at the DB migration challenges. 

## Migration Corner Cases 

In the “<a href="https://www.amazon.com/Refactoring-Databases-Evolutionary-paperback-Addison-Wesley/dp/0321774515/" target="_blank">Refactoring Databases: Evolutionary Database Design</a>” book there are more than 20 cases for the database changes. Some of them can be quite dangerous and cause data loss. 

Of course, you can easily identify refactoring actions that directly delete something. In Jmix we highlight changes that contain such operations as drop table or drop column with red colour in the DB migration scripts.

Let’s have a look at the database update cases that look safe but can cause issues during object model refactoring.

In Jmix, we use Liquibase for DB versioning, so we will use this tool as the reference further in the article. 

## Drop Table/Column

Even though this is a direct action that causes data loss, you can prevent harm by following the simple advice: “do not drop, rename”.

In the “Refactoring Databases: Evolutionary Database Design” book authors almost always use “Transition period” - time interval when DB objects still exist, but not used. It gives us some time to fix issues if something goes wrong with migration. For example, here is the "<a href="https://databaserefactoring.com/RemoveColumn.html" target="_blank">drop column</a>" case representation:

 ![text]({{strapiUrl}}/uploads/blog_img_ca57c30139.png)

## Rename Table

Class rename is a common operation, but in case of data model classes it usually causes DB table rename, especially if we haven’t specified the table name in the `@Table` annotation.

Liquibase will create the <a href="https://docs.liquibase.com/change-types/community/rename-table.html" target="_blank">rename table</a> statement for the operation. It is usually harmless, though it might lock the whole table. Be careful with it when applying the change on the prod server to avoid long downtime due to the table lock.

The potential issue when we renaming a table is not only DB lock, but SQL/JPQL queries specified in the app code in string format. We need to carefully review all such cases, because string references are harder to track than code ones, even with an IDE.

Such code review allows us to prevent the most unpleasant errors - runtime exceptions. 

## Rename Column

Renaming a class attribute is a simple refactoring operation if we use a modern IDE. This operation may cause a renaming operation for the corresponding DB column if we haven’t specified the column’s name explicitly.

As in the case of table rename, if we change a class attribute name, thus table column name, we need to review all related queries (SQL or JPQL) to be on the safe side. 

For the attribute rename operation, the Liquibase tool will generate the “rename column” statement. Direct rename operation is supported by most databases (<a href="https://docs.liquibase.com/change-types/community/rename-column.html" target="_blank">see Liquibase reference</a>). 

In Jmix we still generate “drop column + add column” Liquibase changeset. After it is generated, we need to update it by using the following sequence of operations:

- Add a temporary column
- Copy data from the column that should be renamed to the temporary one
- Drop column
- Create a new column with a new name
- Copy data from the temporary column to the new one
- Drop the temporary column

This will help us to avoid data loss on column rename.

## Replace One-To-Many With Associative Tables

Let’s have a look at the example - we need to store information about cars and their owners. Here is the initial model:

![text]({{strapiUrl}}/uploads/blog_img_2_6b6243fe7f.png)

After some time we realised that we need to store the history of car ownership. When it comes to storing a history, it usually ends up with transforming an association cardinality. And our model transforms into this:

![text]({{strapiUrl}}/uploads/blog_img_3_1f173724a3.png)

With Jmix Studio, changing cardinality is as simple as a couple of clicks in the entity editor. But on the DB level, changes are more serious. Jmix Studio generates the following change sets:

- Create association table
- Add two foreign keys to both entities

The Studio does not remove any foreign key columns from existing tables, we’ll need to do it manually. In our case, the column `person_id` will stay in the `Car` table. 

But the more important thing is that Jmix does not migrate the existing information about links between entities. And if we need to keep this information, we need to migrate the data in the update scripts. 

For the case of replacing many-to-one with associative table, the final changeset should contain the following steps:

- Create association table
- Add two foreign keys to both entities
- Insert data from both tables into associative table
- Drop redundant foreign key in one of the tables

This will allow you to keep history information about links between entities in the new table. 

## Change datatype

We usually do not change class attribute datatype often, in most cases we know the datatype at the business domain modelling stage. But sometimes we have to do it. 

For example, we have a nice delivery tracking application developed for the US market. In the US, ZIP codes can be represented as nine digits (five+hyphen+four). The system works great and it was decided to start selling it for the UK customers. It turns out that in the UK ZIP code has a format like this: “SW1 4HY”. It means that we cannot store ZIP code as a number and should store it as a string.

Changing class attribute datatype is not a big deal, IDE and compiler will catch almost all issues at early stages. But for the database migration is usually a challenge.

In general, we cannot convert a datatype to any other datatype. In Jmix we generate two operators: “drop column” and “add column”. If you apply those directly, your data will be lost. To avoid this, follow the steps described in the “rename column” session.

## Make Column Non Nullable

This change should not cause data loss, but may fail the whole DB update process if the column contains null values. In this case, we need to update the column and add default values. 

Jmix generates only constraint creation Liquibase changeset. You need to change the generated script by specifying default value attribute `defaultNullValue` for null values in the column.

Another option - do not check the existing data by setting the `validate` attribute in the changeset. Before using this we should check if our particular RDBMS supports this feature. For more details can be found in the <a href="https://docs.liquibase.com/change-types/community/add-not-null-constraint.html" target="_blank">Liquibase documentation</a> for this statement. 

## Add Unique Constraint

By adding constraints to a table (whether it is not null or unique key or something else) we introduce a potential failure for the database update process. The problem is that sometimes we just cannot check all possible data sets in all databases that will be updated by our changeset. 

If we decide to add a unique constraint to a table, we can do it in the Jmix Studio by setting the corresponding attribute property or by creating a unique index in the visual editor.

Jmix will generate a base `addUniqueConstraint` Liquibase changeset. If we do not have information about the database that should be updated, we can add the `validate` attribute in the changeset.

For some RDBMSes, if we set `validate` to `true`, the unique constraint will be applied to newly created records only, the old data will not be validated. If we set it to `false`, the changeset will fail if there is non-unique data.

As an example, Oracle supports this mode (with <a href="https://stackoverflow.com/a/42903246/3136181" target="_blank">some tricks</a> though), but PostgreSQL doesn’t. We need to check the docs for our RDBMS to use this option. 

If the DB does not support deferred constraint validation, we’ll have to update the data before applying the index. 

First option - a manual process when we select all non-unique records and update them one-by-one. We’ll need to provide a clean migration instruction for our application that must be followed by DB admins.

If we want to automate the update a bit, we can assign a simple SQL update that will add a unique suffix to existing data in the column(s) that is going to be used in the unique constraint. This update can be added to the liquibase changeset. This option is simpler, but altering data may not be a great idea in some cases.

So, adding a unique constraint is a bit more complex than just issuing one `ALTER TABLE` statement, but it may be resolved with some additional actions stated above. 

## Conclusion

Database Migration is a complex process. Even with the modern tools and frameworks like Liquibase and Jmix you may bump into cases that may cause data loss or application runtime errors. Hope that this article will help you to avoid those pitfalls. 
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Database Lifecycle in Jmix]]></title>
            <link>https://www.jmix.io/blog/database-lifecycle-in-jmix</link>
            <guid>https://www.jmix.io/blog/database-lifecycle-in-jmix</guid>
            <pubDate>Thu, 27 May 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Lifecycle_of_Jmix_21622635708483_e9fe1010ad.png">Jmix is a framework for data-centric application creation. Hence, data model and data access layer play one of the major roles in the framework. We use relational databases and JPA for data access in Jmix.]]></description>
            <content:encoded><![CDATA[## Introduction

Jmix is a framework for data-centric application creation. Hence, data model and data access layer play one of the major roles in the framework. We use relational databases and JPA for data access in Jmix.

JPA abstracts us from DB-specific queries and we work with classes and objects in the application. But you need to be sure that your database schema and object model are in synchronized state. Otherwise, the application might not even start or worse - throw unexpected exceptions in runtime. 

So what do we do in Jmix to avoid such issues and simplify a developer’s life?

## Reasoning about the data model

When we start a project (with any technology) that uses an ORM framework (JPA, iBatis, or any other), we should decide what goes first: a database schema definition or an object model? In Jmix, we recommend starting with the object model definition. The rationale behind this recommendation is simple: we should define a data model where it is used. Since all business logic is processed in the application, defining the object model on the app side looks reasonable. 

An application is not a static thing, business requirements change over time, so the application’s data model changes. It means that we need to change the underlying data storage. 

The times when developers wrote and updated SQL for their applications are long gone. Nowadays we usually use dedicated database versioning tools. Liquibase and Flyway are the most common ones. In Jmix, we use Liquibase for the DB versioning support.

## What is Liquibase?

The official definition of Liquibase is: “Liquibase is an open-source database schema change management solution which enables you to manage revisions of your database changes”.

The key concept is the “changeset” - a single database update like table creation, column removal or constraint update.

Changesets are stored in DB-agnostic scripts in XML, YAML or JSON format - changelogs. You can also write DB-specific changelogs like creating a table with a JSONB column for PostgreSQL and BLOB for other databases.

Usually, in the application codebase there is one “master” changelog that contains directives to include other changelogs. And each time a new changelog is created, it is included into master. 

Liquibase provides a robust framework for running database update scripts. This tool even can create changelogs based on the existing database or comparing two database schemas. We can even generate changelogs for the entities model, if Hibernate is used, but a separate maven plugin is needed. 

## Jmix Scripts Generation

In Jmix, we generate Liquibase changelogs by comparing the JPA data model with the database schema. The development cycle basically consists of the following steps:

- Implement object data model
- Check if all existing changelogs are applied to the DB
- Compare object data model against the DB schema
- Generate a new Liquibase changelog that updates the DB schema according to object model changes

Looks easy, right? The framework does all the heavy lifting for us. But you need to be careful, because not all changes are harmless. Adding a field to an entity (hence a column to a table) is simple. But removing a field may cause data loss. 

Jmix Studio groups database updates and shows unsafe changesets in red color, and a developer can remove them from the changelog if needed.

<img src='{{strapiUrl}}/uploads/Changelog_Preview_d4f761a87b.png' style="width:100%; margin:10px 0;">
 <br>

After generation, the changelog becomes a part of the source code. In Jmix, we store changes, grouping them by date. By default, changelogs are stored in the following folder structure:

<img src='{{strapiUrl}}/uploads/Changelog_Structure_497574bc8b.png' style="width:40%; float:left; margin:10px 0;">
 <br>
 
Every new changelog will be placed in the corresponding folder and included in the main `changelog.xml` file. 

Every time a Jmix application starts, it runs the main changelog using the Spring Boot Liquibase integration bean.

## Database Migration Process

During the development phase we can apply Liquibase changelogs to the dev database using Jmix Studio. Just right-click on the data source in the navigator and select “Update Database”

<img src='{{strapiUrl}}/uploads/Update_Db_Jmix_9607510c82.png' style="width:100%; margin:10px 0;">
<br> 

In case of the prod deployment, we sometimes don’t have access to the prod database. In this case, DevOps or DBA has two options:

- Apply changelogs automatically on the application startup
- Apply manually and then redeploy and restart the application

As it was mentioned above, in a Jmix application, the first option is enabled. If we don’t want to allow our application to update the production database automatically, we need to set the `jmix.liquibase.enabled` property value to `false` in the `application.properties` file.

Jmix keeps changelogs in the same .JAR with the application code. Though Liquibase supports running changelogs packaged into .WAR or .EAR files, it does not support Spring Boot .JAR layout.  If you want to run migration separately, you need to extract and copy changelogs to a separate location manually and run them using Liquibase CLI. 

## Conclusion

Database migration is a challenging task. Fortunately, there are tools that simplify it for a developer. Liquibase provides changelogs execution, validation, checks integrity, etc. 

With Jmix, you can generate changelogs according to JPA model changes, review them and update if needed. Combining Jmix with Liquibase covers the full database schema development lifecycle starting from JPA entities creation to schema update. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Announcing Jmix 0.9 - pre-release version]]></title>
            <link>https://www.jmix.io/blog/announcing-jmix-0.9-pre-release-version</link>
            <guid>https://www.jmix.io/blog/announcing-jmix-0.9-pre-release-version</guid>
            <pubDate>Fri, 02 Apr 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Zaglavnyj_risunok_dlya_stati_pro_reliz_Jmix_0_9_02_cab7ba0272.jpg">Jmix 0.9 is the last pre-release branch that should be considered as “almost stable”. We also deliver the latest version of the companion development tool for the framework - Jmix Studio: 0.9.1-202.
]]></description>
            <content:encoded><![CDATA[Jmix 0.9 is the last pre-release branch that should be considered as “almost stable”. We also deliver the latest version of the companion development tool for the framework - Jmix Studio: 0.9.1-202.

In this release, we have frozen all major APIs: data model definition, data access layer, and security subsystem. They will probably remain the same in Jmix 1.0. Therefore, 0.9 can be considered as a good version for MVP development, and we expect that migration to 1.0 will be near trivial.

Let’s have a look at the most noticeable features in this version in various framework areas.

## Jmix Studio
The first thing that should be mentioned: you can create different types of projects with Jmix. In version 0.9, Studio provides three templates for your Jmix projects:
- *Application* - to create a new Jmix application. 
- *Theme* - to create a CSS theme for your application. A theme can be installed as an add-on.
- *Widget* - this project type simplifies a custom widget creation.  

To assist with project development, the Studio provides a [specialized tool window](https://docs.jmix.io/jmix/latest/studio/tool-window.html). It can help with exploring Jmix-specific configuration files, navigate through the data model, configure data stores, and many other things.

## Core 
The framework core is based on Spring Boot 2.4.2, and we are planning to update it to the latest version - 2.4.4 in Jmix 1.0, needless to say, the update process will not stop in the future versions of the framework. 

As it has already been announced, Jmix uses Liquibase for the database update process. The framework generates database update scripts based on data model changes, similar to CUBA. But in contrast to the predecessor, the scripts are in XML format now, and the same script set can be applied to different database types.

The experienced CUBA developers will definitely notice the explicit definition of the `User` class in the application code, which may be unusual to them. This is a big change compared to the CUBA Platform - we decided to generate key user management functionality classes for every application, to make it simpler to extend or override if needed.

## Backoffice UI
At the moment, all UI components are converted to use the Jmix framework’s API and ready for the stable release. Just a reminder: in Jmix, Backoffice UI is a part of the main project, there is no separation into `core` and `web` modules anymore. 

By default, the generated Jmix project contains Backoffice UI. It is added as a dependency, and you can remove it if you don’t need it. Familiar wizards for screen code generation stay in the Studio, so you will be able to create CRUD screens for your application just in a few clicks as before. 

## React UI
The React UI client generator integration has been significantly improved. We continue developing libraries to simplify ReactJS development with Jmix. Now you can use two libraries: [Jmix React Core](https://docs.jmix.io/jmix-frontend-docs/0.x/jmix-react-core/index.html) - to work with Jmix entities and invoke the services and Jmix React UI - a  set of UI components for the user interface development. 

ReactJS client customization is simpler than before. Similar to Jmix Backoffice UI themes, you can create themes for the front-end client.

## Add-ons
There are six add-ons available on the Jmix marketplace now:
- REST API
- Maps
- Dynamic Attributes
- Entity Log
- Email
- Entity Inspector

We continue working hard on add-ons adoption, you can expect to see Jmix 0.9 compatible BPM and Charts add-ons in the marketplace soon. 

## Conclusion
If you think about adopting Jmix, now it is a good time to start doing that. API is stable, so you won’t need to reimplement your MVP completely because of breaking changes. 

Meanwhile, you can enjoy the updated core that allows you to use Spring Boot starters, better deployment options, including Docker image creation, and keep good old CUBA development speed. 
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The data access layer in Jmix: JPA on steroids]]></title>
            <link>https://www.jmix.io/blog/the-data-access-layer-in-jmix-jpa-on-steroids</link>
            <guid>https://www.jmix.io/blog/the-data-access-layer-in-jmix-jpa-on-steroids</guid>
            <pubDate>Wed, 17 Mar 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/racing_car6_Montazhnaya_oblast_1_71d5275fde.png">The data model is one of the cornerstones of any enterprise application.  In this article, we will discuss the data access layer in Jmix, talk about what can be done with this framework and its tools, and how the data access works under the hood.  ]]></description>
            <content:encoded><![CDATA[## Introduction
The data model is one of the cornerstones of any enterprise application. When you start planning the model, you should not only take into account business data requirements but also answer some additional questions that may affect your application design. For example: do you need row-based security? Are you going to use soft delete? Do we need CRUD API, and who will do this boring job? 

JPA is a de-facto standard for creating a data model for Java applications. This API does not provide facilities to implement advanced security or soft delete, so developers have to implement their own solutions. 

Jmix framework provides a generic engine that adds extra features to applications that use JPA. The framework allows you to enjoy advanced data security, use soft delete transparently, provides generic REST API for CRUD operations and some other features without breaking JPA compatibility. 

In this article, we will discuss the data access layer in Jmix, talk about what can be done with this framework and its tools, and how the data access works under the hood.  
## Data Model, JPA, and @JmixEntity
As a java developer who is familiar with JPA, you don’t need to learn anything new to start working with Jmix. You simply create JPA entities. Jmix provides a GUI designer that assists you with this task. 

<br/>
<img src='{{strapiUrl}}/uploads/New_Entity_c7b1c6cd30.png' style='float:right'>

In the designer, you need to give your entity a name, select the ID type (UUID, Long, Integer, String, or embedded class), and select the features to be supported:
- Versioned - to support optimistic locks
- Audit of creation
- Audit of modification
- Soft Delete

As a result, you will get a JPA class similar to this:

```Java
@JmixEntity
@Table(name = "SPEAKER")
@Entity(name = "Speaker")
public class Speaker {
  
@JmixGeneratedValue
@Column(name = "ID", nullable = false)
@Id
  private UUID id;

@Email
@Column(name = "EMAIL", unique = true)
   private String email;

@Column(name = "NAME", nullable = false)
@NotNull
   private String name;

@Column(name = "VERSION", nullable = false)
@Version
   private Integer version;

@CreatedBy
@Column(name = "CREATED_BY")
   private String createdBy;

@LastModifiedBy
@Column(name = "LAST_MODIFIED_BY")
   private String lastModifiedBy;

@DeletedDate
@Column(name = "DELETED_DATE")
@Temporal(TemporalType.TIMESTAMP)
   private Date deletedDate;

   //Some columns, getters and setters are omitted
}
```

Please note that Jmix is not invasive. The entity does not implement even a single framework-specific interface not to mention inheriting a class, just adds some extra annotations. This gives you great flexibility in creating your own application-specific entity hierarchies that fully meet your business requirements.

Most of the annotations used by Jmix are either from JPA or from Spring Boot JPA libraries: `@Entity`, `@Versioned`, `@CreatedBy`, `@LastModifiedBy` - you could have seen them before. The framework relies on the Spring Boot implementation to support optimistic locking, as well as creation and update audit. 

Let me bring your attention to some Jmix-specific annotations that you will see in your data model:
- `@JmixEntity` - instructs Jmix data access layer to add this class to entities repository
- `@JmixGeneratedValue` - indicates that the entity’s `ID` attribute value must be generated and assigned by Jmix
- `@DeletedBy` and `@DeletedDate` - used to mark fields that indicate that the entity was deleted when you use the soft delete approach

You may ask: “What is an entity repository in Jmix’s data access layer? Do you have your own data access engine?” Yes and no. The framework stores extra information about the application’s data model - metamodel, and adds a special facility - `DataManager` - for data access, but still uses standard JPA under the hood.
## Metamodel and DataManager
Jmix is based on the Spring Boot framework. The latter is known for its extensive usage of the IoC pattern that implies storing all data about beans in the special repository - `ApplicationContext`. In addition to this, Jmix stores all data about your application data model (e.g. metadata) in another repository - `Metadata`. 

`Metadata` is the heart of the data access layer in Jmix. It contains all the information about entities, attributes, entity associations, etc. This information is collected once at the boot time during class scanning and used by Jmix to do its magic: from row-based security to two-way data binding in the generated admin UI. 

To utilize the Jmix data access layer efficiently, you need to use the `DataManager` component. It is a wrapper for the well-known `EntityManager` from JPA. Similar to `EntityManager`, `DataManager` can load entities using JPQL query or ID, save or delete entities as well as count selected instances.

Here are the examples of `DataManager` usage.

Load one instance by `ID` using java class as a parameter:

```Java
Speaker loadSpeakerById(UUID speakerId) {
    return dataManager.load(Speaker.class) 
            .id(customerId)                 
            .one();                         
}
```

Load data using JPQL query string:


```Java
List<Speaker> loadSpeakesByCompanyEmail() {
    return dataManager.load(Speaker.class)
            .query("select s from Speaker s where s.email like :email")
            .parameter("email", "%@company.com")
            .list();
}
```

`DataManager` uses `Metamodel` to provide some extra features by intercepting and modifying requests to the application database before passing them to `EntityManager` for execution. 

Let’s have a closer look at the features that Jmix provides.   
## Advanced Data Security
The first thing that should be mentioned - the Jmix data security subsystem. The framework uses role-based security and defines two types of roles:

1. Resource role - gives users permissions to access objects and perform specific operations in the system: CRUD operations over entities, entity attributes, UI screens, and so on.
2. Row-level role - allows you to restrict access to particular rows of data, in other words - to entity instances.

For the resource role, you can define policies for entity CRUD operations and even operations allowed for entity’s attributes. 

```Java
@ResourceRole(name = "Speaker Admin", code = "speaker-admin-role")
public interface SpeakerAdminRole {

   @EntityPolicy(entityName = "Speaker", 
                 actions = {EntityPolicyAction.ALL})
   @EntityAttributePolicy(entityName = "Speaker", 
                          attributes = "{name, email}", 
                          action = EntityAttributePolicyAction.MODIFY)
   void speakersAccess();
}
```

To implement this, DataManager analyzes JPQL and either restricts its execution or modifies the attributes list to comply with security policies. 

To define a row-level role you should specify a JPQL policy that consists of the `where` and optional `join` clauses that restrict data selected from the DB table. 

```Java
@RowLevelRole(name = "Speaker's Talks",
             code = "speakers-talks-role")
public interface SpeakersTalksRole {

   @JpqlRowLevelPolicy(entityClass = Talk.class,
                       where = "{E}.speaker.id = :current_user_id")
   void accessibleTalks();

}
```

So, all queries that are issued by a user with a row-level role are transformed in the following way: the `where` clause is appended to the existing clause using AND operator, and the `join` condition is appended to the existing one. If either of them does not exist in the JPQL, the corresponding clause is “just” appended.

`Metadata` repository plays an important role here. It helps us to parse and modify JPQL correctly and find restricted attributes and entities whenever string JPQL or a Java class is used to define a DB query. 
## Soft Delete
In some cases, soft delete is required for enterprise applications. The pros and cons of the soft delete pattern were discussed in the article [“To Delete or to Soft Delete, That is the Question!”](https://www.cuba-platform.com/blog/to-delete-or-to-soft-delete-that-is-the-question!/) in the CUBA Platform blog. Jmix is a descendant of CUBA, so soft delete is supported in this framework, too. 

Soft Delete mode is enabled automatically for entities with the fields annotated with `@DeletedBy` and `@DeletedDate`. For these entities, all `remove()` invocations in the DataManager are intercepted and transformed to `UPDATE` statements, and all `find()` requests will be modified with an appropriate `where` clause to exclude the “deleted” entities.

```Java
@JmixEntity
@Table(name = "SPEAKER")
@Entity(name = "Speaker")
public class Speaker {

   @JmixGeneratedValue
   @Column(name = "ID", nullable = false)
   @Id
   private UUID id;

   @DeletedBy
   @Column(name = "DELETED_BY")
   private String deletedBy;

   @DeletedDate
   @Column(name = "DELETED_DATE")
   @Temporal(TemporalType.TIMESTAMP)
   private Date deletedDate;

      //Some fields are omitted
}
```

We need `Metadata` here to find out which database column should be updated or added to where clause. In contrast to CUBA, Jmix does not require an entity to implement a specific interface to support soft delete. All you need to do is just to add two annotations to the entity’s fields. 

Note that you still can perform “hard delete” and see the “deleted” entities using JPA `EntityManager` and native SQL.
##  REST and GraphQL
Automatic CRUD API creation is the area where Jmix’s metamodel shines. When you have all the information about entities in your application, it is pretty easy to create an API for manipulation. 

For example, it should not be hard to handle HTTP requests like this if you have metadata for your data model:

```
GET  'http://server:8080/rest/entities/Speaker'
```

A single endpoint at `/rest/entities` can handle requests for entity manipulations. The application “knows” which entities should be selected if a user sends the GET request for an entity (`Speaker` in our example). Moreover, it costs nothing for an application to provide a Swagger-compatible endpoints schema because we have all the metadata we need. 

Jmix can generate a swagger doc that includes all entities and attributes that a developer can process via REST API, and make it available by a specific URL: 

```
GET  'http://server:8080/rest/docs/swagger.json'
```

For example, a list of endpoints for CRUD operations looks like this:

![RestApi.png]({{strapiUrl}}/uploads/Rest_Api_115cdfb4a6.png)

The good thing is that with Jmix you don’t need to do the boring job of implementing these endpoints manually. Thanks to the metamodel, everything can be generated for you, and it can be a good starting point to build your own specific REST API using the “back-for-the-front” approach.

If you need something more flexible than generic CRUD REST API, you can use GraphQL. One of the key concepts in GraphQL is its schema. With Jmix’s metamodel, we have all the data for the GraphQL schema without extra efforts. 

It means that [GraphQL API for Jmix applications](https://github.com/Haulmont/jmix-graphql) can be implemented (and it is going to be released soon) in a generic way, similar to the REST API. So, adding a GraphQL endpoint to your Jmix application will be as simple as adding one more starter to the build script. 

```
implementation 'io.jmix.graphql:jmix-graphql-starter'
```

After that, you are able to create queries similar to this:

```
{
  speakerCount
  speakerList(limit: 10, offset: 0, orderBy: {name: ASC}) {
    id
    name
    email
  }
}
```
## Conclusion
Just by defining the data model in Jmix, mostly using familiar JPA annotations, you’re getting a ready-to-use application. Thanks to Jmix’s metamodel, you can use the following features almost without extra coding:
- Row-level security
- Soft delete
- CRUD REST API
- GraphQL API

As you see, creating a simple data-centric application with advanced features and admin UI is going to be near trivial with Jmix. 

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix Roadmap 2021-2022]]></title>
            <link>https://www.jmix.io/blog/jmix-roadmap-2021-2022</link>
            <guid>https://www.jmix.io/blog/jmix-roadmap-2021-2022</guid>
            <pubDate>Mon, 28 Dec 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Roadmap_2021_1200x628_20fb78f262.jpg">First of all, let me wish all of you a Happy New Year and congratulate that 2020 is finally over! It has been a rough year for the world, and I hope that 2021 will bring us more positive news. ]]></description>
            <content:encoded><![CDATA[First of all, let me wish all of you a Happy New Year and congratulate that 2020 is finally over! It has been a rough year for the world, and I hope that 2021 will bring us more positive news. 
In this article I would like to recap the results of 2020 for our team, and share some plans for the upcoming 2021.

We kept mostly silent about our plans over the last year. I hope that now, as [Jmix is released](https://www.cuba-platform.com/blog/jmix-the-future-of-cuba-platform/), you can see why. The amount of changes and R&D work meant that it was just too hard to give promises. We needed to be flexible and move at a comfortable pace. 
But even though most of the team was focused on Jmix, we delivered some cool features for CUBA as well:
- Kotlin support and design-time security roles in [CUBA 7.2](https://www.cuba-platform.com/blog/cuba72-whats-new/) 
- The new [Helium](https://www.cuba-platform.com/blog/helium-announce/) theme with a visual theme editor
- Support for React Native in the frontend [generator](https://www.cuba-platform.com/discuss/t/frontend-20-1-beta-published/12275/10) 
- [CUBA SDK](https://www.cuba-platform.com/blog/development-in-isolated-network/), helping to develop your projects in isolated environments
  
Of course, there were hundreds of other evolutionary improvements in Studio, the framework and the frontend generator.

On the community side, we added [Italian](https://www.cuba-platform.it/) and [French](https://www.cuba-platform.fr/) versions of the website and forum. We also rolled out a simplified form for the academic license requests, so [more and more](https://www.cuba-platform.com/blog/cuba-platform-helping-it-education/) universities are using CUBA for their enterprise software courses! 
We welcome new big brands among our customers, including Ingenico and Sber - the largest bank in Eastern Europe. Sber has <a href="https://www.sberbank.ru/en/press_center/all/article?newsID=1ffbb179-f30e-4a14-b230-c04d38123fe5&blockID=1539&regionID=77&lang=en&type=NEWS" target="_blank">signed</a> a large-scale agreement to adapt and use CUBA Studio to speed up the development of applications for in-house users across the whole bank.

## What’s coming in 2021?

The recent release of Jmix provides us a solid foundation, so we look  into the future with confidence. We have ambitious plans and currently we are scaling the team to support them. We expect that over 50 developers will be working on Jmix by the end of next year!

Our first priority is of course the release of a stable version of Jmix. This includes complete documentation, migrating remaining addons and thorough testing. We are aiming at Q2 2021 to finish this work. 

New features are described below. Keep in mind that many of them still require R&D so don’t ask me for implementation details. Still, this should give sufficient clue of where we are heading, and I hope you’ll like it!

## Frontend

Now, as our CUBA backend is rebuilt around Spring Boot, the most widely used server side technology for enterprise projects, it is time to shift focus towards the frontend. Well, to be honest, the time has come a couple of years ago, as Vaadin 8 got outdated. However, we always keep long term sustainability and backwards compatibility in mind. Unfortunately for us, the web frameworks world is changing so fast that it was hard to make a safe bet. Even the Vaadin components set [is still actively evolving](https://www.cuba-platform.com/blog/vaadin-10-evaluation/) in the latest releases. 
So we just had to keep Vaadin 8 UI which, with all its limitations, “just works”. Nevertheless, the frontend team was exploring new approaches in the portal module and recently in the TypeScript SDK and the React frontend generator. You can already scaffold React and React Native clients, though it is still a much more complicated and manual process compared to the Vaadin-based UI. You can plug in any other web framework with the help of Typescript SDK of course, but it is an even more manual process.

Anyway, the quest is over. We believe that React is “here to stay” for long enough. So the main focus for 2021 is to push React UI client to the state when it is as productive and as easy to use as Vaadin. Naturally, this assumes full support in Studio, including visual designer with screen templates, hot reload, theming, and a complete suite of components, at least equivalent to their Vaadin counterparts. As usual, we will try to abstract (not isolate) developers from the intricacies of the JS ecosystem to the possible extent. The benefits are obvious: faster and better scalable UI with wider customization options and massive community support.
However, there is also a price to pay. Basic understanding of Typescript, HTML, CSS will be required. You will also require the commercial IntelliJ IDEA Ultimate for comfortable work with Typescript. We plan to release a version of Studio bundled with it. 

What happens to Vaadin? No worries, its story also continues. We still believe that it is a great choice in many scenarios. It is perfect for backend developers who do not have much love for web stuff. Unless you expect tens of thousands of users or high latency networks it will perfectly do the job, and such assumptions are valid for most back office applications. We keep monitoring the progress of Vaadin folks in the latest versions, and we are expecting to be able to upgrade from version 8 to one of those in 2022. 

What about mobile applications? As mentioned above, we are already supporting React Native client generation, as well as PWA in the React client. In addition, we have started small-scale R&D around <a href="https://flutter.dev/" target="_blank">Flutter</a>, a very promising UI technology backed by Google. Flutter’s ultimate goal is to deliver a single UI technology for all platforms: mobile, web and even desktop. It will also be much more familiar to backend developers, while its ideology is similar to React: everything is a component (aka Widget) and UI is a function of state.
Flutter is gaining traction fast and is already the most popular choice for cross platform mobile apps, while web support is in beta. However, we are yet to see if it becomes mainstream. 

Our main use case - “line of business” applications - assumes manipulating with complex data graphs. So both Flutter and React require a convenient server-side API for this purpose. After some experiments, we ended up with GraphQL, which seems to be a very natural fit and which will become a shared part for both clients.

To wrap it up, Jmix will be supporting more options to deliver frontend of any scale and complexity, for both web and mobile platforms, and both for those who love and hate JS :) 

## DevOps and Clouds

For years, we considered deployment “out of scope” and focused purely on the development side of things. However, we get more and more requests to simplify this side of the application lifecycle too. So we decided to form a “DevOps” team within Jmix to handle this. The task is inline with our general approach: abstract (but - I’ll stress that again - not isolate) the developer from the specifics of underlying technologies like Jenkins, Docker, Kubernetes, Terraform and provide simple and convenient visual tools to configure your environments and CI/CD pipelines.

What this means in practice:
- Configuring, generating and publishing Docker images
- Configuring environments, e.g. test and production
- Describing required infrastructure using a visual designer - based on Kubernetes and Terraform
- Configuring CI/CD pipelines
  
We are planning to rely on public clouds infrastructure - AWS to start with - for part of these features. But AWS (Azure, Alibaba, etc) offers so much more than just hosting your app, that it would be a crime to ignore its capabilities! So we will give you a choice to build truly cloud-native applications on top of cloud services including database, file storage, authentication, full text search, monitoring, logging, load balancing, etc. 

The ultimate goal is to provide you everything to deploy and run your applications in the cloud with minimal efforts. As this is an absolutely new direction, it is hard to declare deadlines. But we are aiming to release a beta version at the end of 2021.  

## Tools

Studio team is gradually becoming the largest in Jmix. Indeed, every direction, be it cloud or frontend, assumes relevant tooling support on the Studio side. In addition, we want to introduce some important enhancements this year:
- New visual designers - for JPQL and GraphQL queries, string messages and simple logical expressions. I hope everyone will love the idea of not having to write JPQL strings!
- Code generation based on templates for typical actions: open a screen, save/load data, show message, invoke a service, start a business process.
- Visual reports configuration at design-time. 
- BPM processes configuration at design-time.

## Moving things to design-time

I would like to highlight the last two features. Up till now, both Reporting and BProc addons only supported configuration at runtime. From one point of view, this is great: reports and business processes can be configured by non-developers without the need to redeploy the application. However, this has a number of side effects:
- If the data model changes, your report or business process may stop working, and you will not even notice it until you run it. 
- Instances of reports and business processes might easily get out of sync between different installations of an application. You may be testing one version on the test stand, at the same time someone changes something in production…
- For complex reports, a developer has to use inconvenient runtime code editors.
- When configuring a business process, a developer has to switch back and forth between Studio and a running application with frequent restarts to add new forms, services, etc.  
  
All in all, this becomes a fragile and cumbersome process, leaving lots of room to errors. Considering this, we decided to implement BPM and report designers in Studio. 
The option to build reports and edit business processes at runtime will also be preserved. You may notice that this is inline with the recently implemented design time support for access groups and security roles.

For reports, this means that a report is becoming a Java class, configured using a Studio wizard. This enables compile time validation, ability to test and debug reports and better visual tools. 

For BPM, the idea is similar. Design-time editor will enable testing and debugging process definitions, as well as creating many things inline: services, forms, handlers and so on. This will result in a seamless developer environment, powerful enough to compete with some BPMS solutions on the market.  

As many other features, we are aiming to release a beta version of these new tools at the end of 2021. 

## Timeline  

Here is the timeline to summarize the expected releases for your convenience:
- Q2 2021 - stable version of Jmix
- Q4 2021 - stable version of the React client
- Q4 2021 - beta versions of:
&nbsp;&nbsp;&nbsp;&nbsp;- DevOps and Cloud tools
&nbsp;&nbsp;&nbsp;&nbsp;- cloud native applications support
&nbsp;&nbsp;&nbsp;&nbsp;- visual reports and business processes configuration at design time
&nbsp;&nbsp;&nbsp;&nbsp;- other tools in Studio
- Q2 2022 - stable versions of everything released in Q4 2021

This is a challenging schedule and some deadlines might slip, but we are determined to do what’s possible to stick to it.

## The Future

Implementing everything described above will mean that Jmix becomes a powerful platform for building modern enterprise applications, providing:
- Scalable UI for mobile and web applications
- Cloud native capabilities and full deployment automation 
- More visual tools, facilitating productive development and easier onboarding
 
In fact, Jmix should become a strong competitor on the blooming Low Code Application Platforms (LCAP) market. With at least the same level of productivity, Jmix addresses many of the LCAP shortcomings, so we hope it will be a fresh breeze on this controversial market. 
Jmix is built for and offers a comfortable working environment for developers, while most LCAPs are focused on business users (aka “citizen” developers) and hence provide poor developer experience. Jmix is also open and flexible enough to build even the most complex applications like ERPs - this fact has been proven multiple times by our community projects. Finally, unlike most LCAPs, it is built around an open source framework - meaning that your applications are truly yours. 

We hope that this combination of Jmix features will help you deliver powerful yet beautiful applications in record time, and will be attracting new members to our community. As usual, your feedback is much appreciated - feel free to leave your comments on the <a href="https://www.cuba-platform.com/discuss/t/jmix-roadmap-2021/" target="_blank">forum</a> or contact us directly. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Jmix - the future of CUBA Platform. More about the new version.]]></title>
            <link>https://www.jmix.io/blog/jmix-the-future-of-cuba-platform</link>
            <guid>https://www.jmix.io/blog/jmix-the-future-of-cuba-platform</guid>
            <pubDate>Tue, 22 Dec 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/acc4b1613e594769a9bb8c417bf4df58_232f83b66e.png">CUBA started its way back in 2008. Since then it went through a few very important stages. At first it was an internal framework with no documentation and even less API. It was a company-wide thing that allowed Haulmont to develop Business Applications faster. ]]></description>
            <content:encoded><![CDATA[## TL;DR 

Jmix is the new name and the new major release of CUBA Platform. It is now in Preview and we are aiming to release Stable version in Q2 2021. Key features:
- Spring Boot as a core technology
- Decomposition into separate pluggable modules (data, security, audit, etc.) 
- A new approach to data model definition
- Database update process based on Liquibase
- Deployment approach utilizing Spring Boot features, allowing better integration with cloud environments.

We will be focused on simplifying ReactJS client development. Meanwhile, we will keep the current Vaadin-based client UI, which will become one of the Jmix modules.

CUBA Platform will be supported for a long time and we are providing a migration path to Jmix via compatibility APIs.

Check the preview release of Jmix on [jmix.io](https://www.jmix.io/). Discuss the new release in the special <a href="https://www.cuba-platform.com/discuss/c/jmix" target="_blank">forum category</a>. 

 
## Introduction

CUBA started its way back in 2008. Since then it went through a few very important stages. At first it was an internal framework with no documentation and even less API. It was a company-wide thing that allowed Haulmont to develop Business Applications faster. 

In 2015 CUBA was introduced world-wide under a proprietary license. We got just a few users that year - that was embarrassing. It became obvious that the licensing policy should be switched to open source. 

2016 and 2017 were very productive years when we got our wider community. This was a big shift in mind, we saw what was right and what was wrong.

 In 2018-2019 we started to introduce a clear and well-documented API level and moved CUBA Studio onto IntelliJ. All that brought an even bigger community with even more feedback. Now we are staying at the border of the next major update. Let's dive into and see what will come in 2021.

## New version objectives

In the next version of CUBA Platform we wanted to do the following:
1. Make developer’s experience closer to the most popular frameworks. CUBA Platform uses Spring, but nowadays Spring Boot has almost conquered the world. New frameworks are emerging - Micronaut and Quarkus. They all have similar principles at its core: simple configuration via .properties or .yaml files, extensive annotation usage, and simple add-on connection and configuration. So we want CUBA to give a similar experience to developers.
2. Do not reinvent the wheel. Since 2008 a lot of new libraries and tools have been developed. Now they are mature and can be used for enterprise-grade applications. So we wanted to replace some custom CUBA’s modules with battle-proven libraries. As an example - database migration system.
3. Make CUBA applications smaller. When creating applications with CUBA, you don’t always need all the features like audit. But it always has been a part of the framework core, polluting the database with unnecessary (for your particular case) tables and starting extra services on your app server. So, it would be nice to have the ability to exclude some CUBA features and include them only when necessary.
4. And the most important thing - keep great experience and application development speed.
 
And the first thing that we will start from is...

## Naming

“What does CUBA stand for?” - It's hard to count how many times we have been asked this question. Honestly, it was just a name not too long and not too short to name the first package of our internal framework back in 2008. If you dig into CUBA core, you can also find “chile” and “bali” packages. 

In 2021 we’re going to release a new major version - and the name will change. “CUBA” becomes “Jmix”. This name is much simpler to explain: “J” for “Java” and “mix” for the technologies and frameworks mix in one application. Less questions, no associations neither with the well-known island nor with the well-known alcohol cocktail. 

Effectively Jmix is the next major CUBA version with well-known APIs and development approach. And it is still the same set of convenient tools and code generators. 

But renaming, which is a big part, also shows a big change in the...

## Core technology

In a wide sense, in CUBA we were copying some of Spring Boot approaches. Our own session storage, security subsystem, auth… and of course deployment. Also, CUBA add-ons were introduced as a response to Boot starters with their own encapsulation and autoconfiguration mechanism.

When we started CUBA development back in 2008, we used “pure” Spring in the framework core. In Jmix we will use Spring Boot as our core technology. 

Using Spring Boot gives us the following advantages:

1. Better developer experience. Currently almost every Java developer is familiar with Spring Boot. With Jmix, Spring Boot development experience can be used at its full, no need to learn a new framework, just new starters.
2. As for starters, Spring Boot - based core allows us using almost all existing starters in our framework. So, we can rely on existing infrastructure with huge community support and tremendous documentation base.
3. And one more thing - Spring Boot has great features regarding deployment, including great containerization support, out-of-the box. 

When mentioning Spring Boot starters, we cannot forget CUBA add-ons. And this brings us to...

![text]({{strapiUrl}}/uploads/c1a763a2f95443c1821b4275b7e4eea3_662b98d9f2.png)

## Modularization

From time to time we get feedback that an “empty” CUBA application that does not contain a single line of a business logic has too many tables and a lot of functional pieces that are never used. 
In the 7th version of the framework, we started extracting core functionality to separate add-ons. Basically, CUBA is a set of APIs, and this approach provided enough flexibility to be able to continue the modularization process. 

Starting from Jmix, you can use the features of the framework (e.g. audit, security) separately and almost independently. All features are now provided as Spring Boot starters.  For example, there was an audit functionality in CUBA, which is now a separate module in Jmix. And this module in its turn is split into Core and UI modules. It means that you can use the audit engine as a whole module or use only the core engine and implement your own custom UI instead of the provided one.

Some functionality like healthcheck is replaced with Spring Boot actuator (see “Do not reinvent the wheel” section).

Jmix provides more than 20 starters that can be used. Here are some starters and dependencies:

|Feature                                         | Starter                                 | Depend On |
|-------------------------------------|--------------------------------|---------------|
|Entity log                                     |Audit                                      |Data             |
|File storage                                  |Core                                       |                     |
|User settings                               |UI Persistence                       |Data             |
|Table presentations                    |UI Persistence                       |Data             |
|Entity log                                     |Audit UI                                 |Audit, UI      |
|Config properties stored in DB |Core                                       |                     |
|Restore deleted entities             |Data tools                             |Data, UI        |
|User sessions                               |Core                                      |                     |
|Dynamic attributes                     |Dynamic attributes              |Data, UI       |
|Entity Snapshots                         |Audit                                     |Data             |
|Related entities                           |Advanced Data Operations|Data, UI       |
|Bulk editor                                   |Advanced Data Operations|Data, UI       |



As you can see, “data” starter is used by almost all Jmix modules. And it is not a surprise, because one of the strongest sides of the CUBA Platform was its...

## Data access layer

We’re going to introduce a lot of changes here, keeping all the best parts of CUBA and introducing new features that will help you to be more productive.

With all the advantages, CUBA’s data model has one fundamental flaw: it is pretty rigid. For example, if you needed soft delete, you had to implement a proper interface (or inherit your entity from `BaseEntity`) and introduce columns with predefined names in the corresponding table. All primary keys had to be stored in the column with the `id` name if you used the `StandardEntity` class. 

This led to limitations during new data model development. And it also caused a lot of issues when developers tried to implement applications with CUBA using an existing data model. This was a case when CUBA was used as a modern framework to migrate from legacy or unsupported frameworks.

In Jmix, the Entity model becomes more flexible. You don’t need to extend the StandardEntity class or implement the Entity interface anymore. Just add the annotation `@JmixEntity` to a class to make it accessible to the framework. 

We decided to deprecate interfaces that specify an entity’s functionality. They are replaced with common annotations. For example, we use JPA’s `@Version` annotation and Spring Boot’s `@CreatedBy` instead of proprietary `Versioned` and `Creatable` interfaces. 

This allows us to make code more explicit - you can tell which features are supported by the entity by just looking at its code. 


```
@JmixEntity
@Table(name = "CONTACT")
@Entity(name = "Contact")
public class Contact {

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "ID", nullable = false)
   private Long id;

   @Version
   @Column(name = "VERSION", nullable = false)
   private Integer version;

   @InstanceName
   @NotNull
   @Column(name = "NAME", nullable = false, unique = true)
   private String name;

   @LastModifiedBy
   @Column(name = "LAST_MODIFIED_BY")
   private String lastModifiedBy;

   @Temporal(TemporalType.TIMESTAMP)
   @LastModifiedDate
   @Column(name = "LAST_MODIFIED_DATE")
   private Date lastModifiedDate;

```

“CUBA Views” are now “Fetch Plans”. The new name describes the purpose of these artifacts much better. 

Jmix’s data access layer now supports automatic lazy loading of references. So if you choose not to use fetch plans for filtering out local attributes, you will never get the notorious “UnfetchedAttributeException” anymore.

Another big thing is the database generation and update process. We decided to use Liquibase instead of the custom DB update engine. Spring Boot is responsible for running these scripts. This is another example of “not reinventing the wheel” - using a well-known engine with good documentation. 

Liquibase can generate DB-agnostic update scripts, so if you develop a product or an add-on with Jmix, you won’t need to generate database creation scripts for all possible RDBMSes. Liquibase will use the appropriate SQL dialect depending on a JDBC driver. At the same time, it allows DB-specific SQL customization, if you need it. 

And we keep the good old CUBA magic. Whenever you change an entity, Jmix Studio will generate a Liquibase script entry to reflect the changes.

What else can we think about when we talk about CUBA? Of course, it is the framework’s advanced... 

## Security

In Jmix security is a separate module. Now you can choose whether or not you want the CUBA security engine or something else. 

And we reworked our security engine, now it is tightly integrated with spring-security. In order to simplify things for developers and “do not reinvent the wheel” concept, we’ve replaced our custom engine with the “standard” framework that has a lot of documentation and is familiar to developers. The model has changed accordingly - in Jmix we use classes from Spring Security like UserDetails and SessionRegistry, so it might look a bit unfamiliar at the beginning. 

Roles have changed too - we have merged Roles and Access Groups to simplify security management. In addition to this, we’ve added an “Aggregation Role”. This is a role that is composed from other roles - there were a lot of requests from users about this feature. 

Spring security is not the easiest thing to set up but in Jmix we made this process as seamless as possible. You will be able to set access to entities, attributes, screens, as well as set up row-based security as it was in CUBA.

And as it was in CUBA, all you need to do to install the security into your application is to add a dependency to your project and Jmix will do its magic - you will have security set up as well as user management UI (if you want to).

Apart from security, there is one more thing that everyone liked about CUBA: the simplicity of the development of an application’s...

## User Interface

Backoffice UI (a.k.a. Generic UI) stays intact. Component-based UI was a big part of CUBA and we’re planning to support it in Jmix. Support includes screen generators, UI editors in the IDE, etc. We have added new components like a separate Pagination component or ResponsiveGridLayout. The only difference - now you can exclude Generic UI from the application completely thanks to the modular structure of the Jmix framework. 

Please note that Jmix applications are single-tiered; there is no more “core-web” separation. This approach is simpler and fits into the modern architectural approach. If you want a separation, you can achieve it by implementing two Jmix applications and create a REST API for communication. In this case, UI won’t depend on the data model and you will pass DTOs in order to display data on the front-end or process it on the back-end.

When we were planning the new version of our framework, we could not ignore the rise of JS UI frameworks. So we started developing ReactJS client generators (front-end module) in CUBA 7 and we continue this work in Jmix. JS frameworks usually have a pretty steep learning curve, so our aim is to make the ReactJS development experience with Jmix closer to Generic UI development. 

We have introduced TypeScript SDK and developed a set of custom ReactJS components that can be used for the UI development. The front-end module relies on the Generic REST API which is familiar for CUBA developers. The IDE supports basic UI generation with ReactJS. 

For now a developer can generate a familiar “browser” and “editor” UI screens using our components. Later we plan to add more components and simplify ReactJS UI development in the Studio. 

And now we have discussed almost all major changes in Jmix, but it would be unfair not to mention...
![text]({{strapiUrl}}/uploads/9b0dd8c1ff404e01aa0d9e90b1729b2e_716b21f236.png)

## Deploy

CUBA has two deploy formats: WAR and UberJar and two options: a single app deployment or a separate applications deployment (core+web+...). 
 
Jmix will use Spring Boot build plugins for application deploy. It means that you can run a Jmix app as an executable fat JAR or deployable WAR (it also can be executed as a standalone application). 

But the best thing here is containerization. Now you don’t need to create your own Docker file to create an application image, its generation is supported out-of-the-box. Also, you can create layered JARs to make Docker images more efficient. In addition to this, cloud native buildpacks are supported. 

So, Jmix applications will use the cutting edge technologies for deployment in modern cloud environments.

And with so many changes, how about...

## Migration from CUBA to Jmix

First thing: we are not going to abandon CUBA. Version 7 is going to be long-term-support and will be supported for five years. And after that, there will be commercial support available for the next five years. So, CUBA framework will live for at least next 10 years.

At the moment Jmix is at Preview stage, so we’re going to stabilize it for some time before announcing production-ready stable release - provisionally in Q2 2021. But if you plan to start using CUBA, have a look at Jmix first. It is stable enough to start PoC development. And remember that almost all Spring Boot ecosystem is at your service. 

For backward compatibility purposes, we have introduced a jmix-cuba module. This module contains most of the APIs implemented in CUBA. So, you won’t need to change your code much in order to migrate to the next framework version. The compatibility module will be added automatically to your application during migration.

Most CUBA add-ons will be gradually migrated to Jmix platform: reporting, maps, business processes. As we did with CUBA 7 before, we might deprecate some modules when moving to Jmix because there is a Spring Boot starter with the same functionality.

The add-ons format has changed, but functionality stays the same. You can extend entities and screens using the same technique that was used in CUBA. As for services override, you’ll need to use Spring Boot approach - just mark the add-on service with the Primary annotation and functionality will be replaced. 

As usual, when the major version is introduced (basically, Jmix is CUBA 8), some breaking changes may appear. And those changes, as well as workarounds, will be described in details in the documentation. 

And the big part of the migration is the new Studio. Jmix Studio plays a very important role in the framework ecosystem. So, you still be able to use all familiar designers (entity and UI), shortcuts and intentions. And Jmix Studio will help you with creating applications using the framework. 

## Conclusion

Jmix is the next big step in CUBA Platform evolution. Now you can enjoy almost all Spring Boot starters and use techniques applicable for the most popular Java framework in the world. At the same time you still have all the convenient and familiar APIs and functionality provided by Jmix - a CUBA descendant as well as great development experience with the new Studio.  




]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[To Delete or to Soft Delete, That is the Question!]]></title>
            <link>https://www.jmix.io/blog/to-delete-or-to-soft-delete-that-is-the-question</link>
            <guid>https://www.jmix.io/blog/to-delete-or-to-soft-delete-that-is-the-question</guid>
            <pubDate>Fri, 12 Jun 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/Hamlet_305f61ab0b.png">Soft deletion is a widely used pattern applied for business applications. It allows you to mark some records as deleted without actual erasure from the database. Effectively, you prevent a soft-deleted record from being selected, meanwhile all old records can still refer to it.]]></description>
            <content:encoded><![CDATA[Soft deletion is a widely used pattern applied for business applications. It allows you to mark some records as deleted without actual erasure from the database. Effectively, you prevent a soft-deleted record from being selected, meanwhile all old records can still refer to it.

## When would it make sense to use Soft Delete?

If you ask a few developers randomly, most probably you will hear that soft deletion is used to be able to restore deleted records. However, if this is the only business requirement that pushes you towards integrating soft-deletion - think twice. 
Consider the following requirements in addition to “simple data restore” before making a decision on using soft deletion in your project:
1. History tracking and audit (e.g. for legal reasons)
2. Keeping reference integrity and avoid cascade delete
3. You need “Graceful” delete. E.g. a long-running business process may need data that might be “deleted”, but still required for this particular process to finish

If you see that your business requirements match the list above, it means that you may need to implement the “Soft Delete” feature in your application. 

And implementing soft delete is easy! You just add the “Is_Deleted” or “Delete_Date” column to your tables (or attributes to your Document) and replace all delete statement invocations in your application code to updates. And yes, you need to modify all retrieve statements to take into account this new attribute. Or is it better to create a view? Or a materialized view? In this case, we may need to implement “instead of” triggers or stored procedures API to deal with views. And by deleting an entity you may want to delete some attributes it refers to. In this case, to be able to restore it is also required to store deletion context. And… this is where a developer’s life gets complicated. 

## Challenges of Soft Deletion

In fact, implementing “proper” soft delete is not an easy task. Sometimes developers choose NOT to implement soft delete just because it takes a lot of efforts. You might think about other options like table mirroring with the special “trash can” table that contains deleted records from the “original” table. 

But if it is decided to go forward with the soft delete implementation, you need to take into account some conditions.

**Database support.** One of the issues with records that were marked as deleted is their unique keys. As an example - we need to store users along with their emails. Emails must be unique, therefore, we need to create a unique index for the table that stores users. And if a user is deleted, we should be able to insert a new user with the same email. So, your database should be able to handle such cases. One of the options - include a soft delete marker field into the unique key. If your marker field is not a simple boolean value, but delete timestamp, it may do the trick. 

Another option - special unique indexes. For example, in PostgreSQL it is called partial <a href="https://www.postgresql.org/docs/12/indexes-partial.html" target="_blank">unique indexes</a>, in MSSQL - <a href="https://docs.microsoft.com/en-us/sql/relational-databases/indexes/create-filtered-indexes" target="_blank">filtered indexes</a>. They allow you not to take some rows into account when building indexes by specifying a predicate. So, for the soft delete feature implementation, we can exclude “deleted” records from the index.

If your database supports triggers for views, there is a good chance that you can create your data model using views and `instead of` type of triggers. But this approach causes performance impact and does not resolve the issue with unique constraints applied to the underlying table(s).

**Application Support.** Make sure ALL queries mentioning soft-deleted entities are double-checked, otherwise it can lead to unexpected data leaks and critical performance issues. In the ideal world, a developer should not be aware about soft delete existence. So, if possible, try to introduce your data access API and prevent developers from using other facilities to access a database (like direct JDBC connection). You might even want to override standard APIs like JPA’s Entity Manager to support soft delete properly. 

**Revisit standard APIs usage.** First of all, forget about using some of the standard DB and JPA features. If you have your database table and constraint model carefully engineered and tuned, as well as you JPA layer, introducing soft delete requires you to consider the following:

1. Standard cascade policies will not work. Remember that in case of soft delete, you don’t delete records, you update them. If you still need cascade delete, triggers may help you to implement this behavior.  
2. As for the triggers - you’ll need to review them, too, to ensure that the code from pre- and post- delete triggers is executed in pre- post- update triggers during update-as-soft-delete and not executed during “common” update process.
3. JPA lifecycle callbacks `@PreRemove` and `@PostRemove` will not work. Again, look for other options to implement the functionality that is coded in those callbacks. The rule here is similar to the one applied to triggers - in update-related callbacks you need to distinguish between update and soft delete processes. 

**You still need to meet regulatory requirements.** As an example - GDPR. The regulation says that the data must be completely removed if it is required by a user. To comply with this you still need to implement a “purge” process in addition to soft delete. And this purge procedure affects related data in your database in most cases. So, you need to be careful and not to delete business-critical data. 

## Soft Delete implementation in Jmix

Soft deletion mechanism in Jmix is transparent for application developers. All you have to do to make an entity “soft deletable” is to add a couple of attributes with @DeletedDate and @DeletedBy annotations. The framework will recognize them as a “soft delete trait”, and behave appropriately: it will mark deleted records instead of actually removing them, and ignore soft deleted records when loading entities by Id or by any JPQL query. Moreover, when loading object graphs, deleted records will be transparently filtered out from to-many collections!

To cascade soft deletion, Jmix offers @OnDelete and @OnDeleteInverse annotations that can be used with reference attributes. They allow you to express cascade operations on the application level instead of the database-level ON DELETE CASCADE or ON DELETE SET NULL rules.

When it comes to uniqueness, Jmix still relies on database constraints, and soft-deleted entities with unique attributes require creation of partial unique indexes mentioned above.

The magic of transparent handling of soft-deleted records in Jmix is based on the own implementation of JPA EntityManager, which transforms queries automatically adding conditions to filter out deleted records. And the soft deletion logic can be turned off for a particular query, so the application can get the records marked for deletion, if needed. It can be used to review, restore, or wipe out the soft deleted data.

<div class="cta-bottom"><div class="cta-bottom-descr">Watch how to make a simple working application in 12 minutes.</div><a href="/learn/quickstart/" class="btn invert">Try Jmix</a></div>

## Conclusion

Using soft-deletion even for one entity will lead you to a bunch of new development conventions. You need to keep in mind that the delete process is not just delete, but sometimes the update, and not all data in a database table should be available for the application. It means that your code should be engineered in a way to take all that into account in all application tiers - from database schema (document structure, etc.) to user interface (even that). 

With a proper framework you will be able to resolve all these problems, but you should still keep in mind that you have “deleted” data that still exists, and build coding standards and conventions that take this into account.

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[UTF-8 in HTTP headers]]></title>
            <link>https://www.jmix.io/blog/utf-8-in-http-headers</link>
            <guid>https://www.jmix.io/blog/utf-8-in-http-headers</guid>
            <pubDate>Fri, 16 Nov 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/3b46463457d44624bd49c2c0b85bc37a_4e451bc3fe.jpg">HTTP 1.1 is a well-known hypertext protocol for data transfer. HTTP messages are encoded with ISO-8859-1 (which can be nominally considered as an enhanced ASCII version, containing umlauts, diacritic and other characters of West European languages).]]></description>
            <content:encoded><![CDATA[HTTP 1.1 is a well-known hypertext protocol for data transfer. HTTP messages are encoded with ISO-8859-1 (which can be nominally considered as an enhanced ASCII version, containing umlauts, diacritic and other characters of West European languages). At the same time, the message body can use another encoding assigned in "Content-Type" header. But what shall we do if we need to assign non-ASCII characters not in the message bodies, but in the header? Probably the most well-known case is setting a filename in "Content-Disposition" header. It seems quite a common task, but its implementation isn’t obvious.

TL;DR: Use the encoding described in <a href="https://tools.ietf.org/html/rfc6266#section-5" target="_blank">RFC 6266</a> for "Content-Disposition" and transliterate to Latin in other cases.

## Introduction to encodings

The article mentions US-ASCII (usually named just ASCII), ISO-8859-1 and UTF-8 encodings. Here is a small intro to these encodings. This paragraph is for developers who rarely work with these encodings or doesn’t use them at all, and have partially forgotten them. If you’re not one of them, skip this part without hesitation.

**ASCII** is a simple encoding with 128 characters, including Latin alphabet, digits, punctuation marks, and utility characters.

![text]({{strapiUrl}}/uploads/fa96286506be47f58c4761ef92268d28.PNG)

7 bits is enough to represent any ASCII character. The word "test" in HEX representation would look as 0x74 0x65 0x73 0x74\. The first bit of any character would always be 0, as the encoding has 128 characters, and a bite gives 2^8 = 256 variants.

**ISO-8859-1** is an encoding aimed for West European languages. It has French diacritic, German umlauts, etc.

![text]({{strapiUrl}}/uploads/7626aaeeeefc43538d57e1fe62bd1201.PNG)

The encoding has 256 characters, thus, can be represented with 1 byte. The first half (128 characters) fully matches ASCII. Hence, if the first bit = 0, it’s a usual ASCII character. If it’s 1 - we recognize a specific ISO-8859-1 character.

**UTF-8** is one of the most famous encodings alongside with ASCII. It is capable of encoding 1,112,064 characters. <a href="https://tools.ietf.org/html/rfc3629#section-3" target="_blank">Each character size is varied</a> from 1 to 4 bites (<a href="https://tools.ietf.org/html/rfc2279#section-2" target="_blank">previously the values could be</a> up to 6 bites).

![text]({{strapiUrl}}/uploads/86b13d712f144916b5b63a571881aaf9.PNG)
![text]({{strapiUrl}}/uploads/2bc45c6c5af14ea98671c95eeecd669c.PNG)

The program processing this encoding checks the first bit and estimates the character size in bytes. If an octet begins with 0, the character is represented by 1 byte. 110 - 2 bytes, 1110 - 3 bytes, 11110 - 4 bytes.

Just like in case with ISO-8859-1, the first 128 well match ASCII. That’s why texts using ASCII characters will look absolutely the same in binary representation, regardless of the encoding used: US-ASCII, ISO-8859-1 or UTF-8.

## UTF-8 in message body

Before we proceed to headers, let’s see how UTF-8 is used in message bodies. For that purpose we use **"Content-Type"** header.

![text]({{strapiUrl}}/uploads/ac24b06dd3b64bcbbbdd9b943fa7240e.PNG)

If "Content-Type" isn’t assigned, a browser must process messages as if they were in ISO-8859-1\. <a href="https://tools.ietf.org/html/rfc2616#section-3.4.1" target="_blank">A browser shouldn't</a> try to guess the encoding, and it certainly shouldn’t ignore "Content-Type". So, if we transfer UTF-8 messages, but do not assign encoding in headers, they will be read as if they were encoded with ISO-8859-1.

![text]({{strapiUrl}}/uploads/55ddba78bb2b40c19d2ed9c2491e60c2.PNG)

## Entering an UTF-8 message in a header’s value

In case of a message body, everything’s rather simple. A message body always follows a header, so there’re no technical problems here. But what shall we do with headers? The specification <a href="https://tools.ietf.org/html/rfc2616#section-4.2" target="_blank">claims directly</a>, that the order of headers in messages doesn’t matter. I.e. it’s not possible to assign an encoding for one header via another.

What if we just write a UTF-8 value into a header? We saw that with such a trick, applied to a message body, the value will be read in ISO-8859-1\. Therefore, we can assume that the same will happen to a header. But no, it won’t. In fact, for most, maybe even for all, cases such a solution will work out. Such cases include old iPhones, IE11, Firefox, Google Chrome. The only browser refusing to read such a header, of all the browsers I had when writing this article, was Edge.

![text]({{strapiUrl}}/uploads/27f1b23757954ea4b6c55cdbd98f1069.PNG)

Such behavior is not described in specifications. Probably, the developers of browsers decided to go easy on other developers and detect the UTF-8 encoding of messages automatically. Generally speaking, it’s a simple task. Check the first bit: if it’s 0, then it’s ASCII, if 1, then it’s probably UTF-8.

Isn’t there anything in common with ISO-8859-1, in that case? Actually, almost none. Let’s use a UTF-8 character of 2 octets as an example (Russian letters are represented by two octets). In binary representation, the character will look the following way: _110xxxxx 10xxxxxx_. In HEX representation: _[0xC0-0x6F] [0x80-0xBF]_. In ISO-8859-1 those symbols can hardly be used to express something sensible. Therefore, there’s very little chance that a browser will decode a message in a wrong way.

However, you can face some problems when trying to use this method: your web server or framework can simply forbid writing UTF-8 characters into a header. For example, Apache Tomcat enters 0x3F (question mark) instead of UTF-8 symbols. Of course, this restriction can be circumvented, but if an application slaps you on the wrist and doesn’t let you do something, then you probably shouldn’t do it.

No matter if your framework or server forbids or lets you write UTF-8 messages in a header, I don’t recommend doing that. It’s not a documented solution and can stop working in browsers at any moment.

## Transliteration

As I see it, transliteration is a better solution. Many popular Russian resources don’t mind using transliteration in filenames. It’s a guaranteed solution which wouldn’t break with new browser versions release and which isn’t necessary to be tested separately on each platform. Although, you should certainly think of the way of transferring all the possible range of characters, which can be not so easy. For example, if an application is aimed to a Russian audience, the filename can contain Tatar letters ә and ң, which should be somehow handled, not just replaced with "?".

## RFC 2047

As I’ve already mentioned, Tomcat didn’t let me enter UTF-8 in a message header. Is this feature mentioned in Javadocs for servlets? Yes, it is:

![text]({{strapiUrl}}/uploads/e26a3e2900bc4fea8de7a93cc4ab9130.PNG)

It mentions <a href="https://tools.ietf.org/html/rfc2047" target="_blank">RFC 2047</a>. I tried to encode messages using this format - the browser didn’t get the idea. This encoding method doesn’t work for HTTP anymore. However, it used to. <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=601933" target="_blank">For example, here's a ticket</a> on deleting this encoding support from Firefox.

## RFC 6266

The ticket mentioned above <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=601933#c2" target="_blank">says</a>, that even after the support of RFC 2047 stops, there’s still a way to transfer UTF-8 values in downloaded files names: <a href="https://tools.ietf.org/html/rfc6266" target="_blank">RFC 6266</a>. From my point of view, today it’s the most optimal and correct decision. Many popular Internet resources use it. We in <a href="https://www.jmix.io" target="_blank">Jmix</a> also use this RFC for "Content-Disposition" generation.

<a href="https://tools.ietf.org/html/rfc6266" target="_blank">RFC 6266</a> is a specification describing the use of “Content-Disposition” header. The encoding itself is closely described in <a href="https://tools.ietf.org/html/rfc8187" target="_blank">RFC 8187</a>.

![text]({{strapiUrl}}/uploads/e4da8e894c3845f1b2076e271f61ec36.PNG)

Parameter “filename” contains the name of the file in ASCII, “filename*” in any other necessary encoding. If both attributes are defined, “filename” is ignored in all modern browsers (including IE11 and old Safari versions). The oldest browsers, on the contrary, ignore “filename*”.

In this encoding method, first you assign the encoding in a parameter, after '' comes the encoded value. Observed characters of ASCII don’t require encoding. Other characters are just written in hex representation with "%" before each octet.

## What should be done with other headers?

Encoding described in RFC 8187 isn’t generic. Of course, you can enter a parameter with * prefix in a header, and it would probably work for some browsers, but <a href="https://tools.ietf.org/html/rfc8187#section-4" target="_blank">specification dictates</a> not to do so.

Currently, in each case, where UTF-8 is supported in headers, there’s a direct mention of the relevant RFC. Besides "Content-Disposition" this encoding is used, for example, in <a href="https://tools.ietf.org/html/rfc5988#section-5.5" target="_blank">Web Linking</a> and <a href="https://tools.ietf.org/html/rfc7616#section-3.9.2" target="_blank">Digest Access Authentication</a>.

It should be taken into account that the standards of this area are constantly changing. The usage of above-mentioned encoding in HTTP <a href="https://tools.ietf.org/html/rfc5987" target="_blank">was offered only in 2010</a>. The usage of this encoding in the very "Content-Disposition" <a href="https://tools.ietf.org/html/rfc6266" target="_blank">was committed in the standard of 2011</a>. Despite the fact that these standards <a href="https://www.rfc-editor.org/info/rfc6266" target="_blank">are only on "Proposed Standard" stage</a>, they are supported everywhere. It is quite possible that new standards are going to appear, the standards that will allow us to work with various encodings in headers more consistently. So, we only need to follow the news about the HTTP standards and their support level on the browser side.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Code Generation in CUBA: What makes the magic]]></title>
            <link>https://www.jmix.io/cuba-blog/code-generation-in-cuba-what-makes-the-magic</link>
            <guid>https://www.jmix.io/cuba-blog/code-generation-in-cuba-what-makes-the-magic</guid>
            <pubDate>Tue, 10 Nov 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/7fdcbb21ecb34c94a43b05bb653236a4.jpg">Code generation is a common thing in modern frameworks. Like every technology, code generation has application areas and limitations. In this article, we will have a look at code generation usage in CUBA Framework nowadays and discuss the future development of this technique.]]></description>
            <content:encoded><![CDATA[## Introduction

Code generation is a common thing in modern frameworks. There may be different reasons behind introducing code generation - from getting rid of boilerplate code to reflection replacement and creating complex solutions based on domain-specific languages.

Like every technology, code generation has application areas and limitations. In this article, we will have a look at code generation usage in CUBA Framework nowadays and discuss the future development of this technique.

## What is generated in CUBA?
CUBA framework is built over the well-known Spring framework. Basically, every CUBA application can be treated as a Spring application with some additional APIs added in order to simplify the development of the common business functionality.

CUBA provides a Vaadin-based library for quick UI development. And this library uses declarative data binding approach. Therefore, it is possible to display different object property values in the same UI widget by switching binding in runtime. 

It means that every object should be able to provide a property value by its string name. Having the Spring framework in the core means that reflection can be used easily to fetch property values. 

### Entities Enhancement
Reflection is a powerful thing, but it is still slow despite all the optimization efforts of the JVM team. And when we talk about UI, especially displaying big data grids, we come to the conclusion that reflective methods will be invoked pretty frequently. E.g. displaying 20 lines with 10 properties easily leads to 200 invocations. Let’s multiply it by amount of users and take into account that all these invocations will happen on the app server (it’s the way Vaadin works), and we may get a pretty good workload for the server.

So, for every data object (entity) class we need to define a simple method that will invoke a property getter (or setter) based on the property name. The simple switch statement will do. 

Also, the UI needs to “know” if an object was changed, so that a user could confirm data changes when the screen is closed. So, we need to inject a state listener into every object’s setter to check if the property’s value has changed.

And in addition to the method that sets or gets property values, we need to update every setter and invoke a state change listener to mark the entity object as changed. 

This method is also not complex, basically one-line. But it would be unfair to ask a developer to do the boring job - adding and updating a bunch of very simple methods for every entity’s property. And that’s exactly the case where code generation shines. 

CUBA uses EclipseLink ORM under the hood. And this framework solves some tasks stated earlier. As it is said in the [documentation](https://www.eclipse.org/eclipselink/documentation/2.7/concepts/app_dev005.htm): “The EclipseLink JPA persistence provider uses weaving to enhance both JPA entities and Plain Old Java Object (POJO) classes for such things as lazy loading, change tracking, fetch groups, and internal optimizations.”

In CUBA, EclipseLink’s static weaving is invoked in build-time (it is executed at run-time by default) by the CUBA build plugin.

In addition to this, invoking change listeners is still a task that should be resolved by CUBA. And it is done by the build plugin at build-time. So, if you open an entity’s `.class` file, you can see a number of methods that you don’t see in your source code. And you may be surprised to see how your setters changed. For example, instead of:

```
public void setName(String name) {
   this.name = name;
}
```
In the decompiled code you will see:

```
public void setName(String name) {
   String __prev = this.getName();
   this._persistence_set_name(name);
   Object var5 = null;
   String __new = this.getName();
   if (!InstanceUtils.propertyValueEquals(__prev, __new)) {
       this.propertyChanged("name", __prev, __new);
   }
}
```

This is the mix of code generated by EclipseLink weaver and CUBA build plugin. So, in CUBA compiled entity classes are different from what you actually write in the IDE. 

### Bean Validation Messages
CUBA Platform supports internationalization for the bean validation messages. It means that in JPA validation annotations you can refer to `.properties` file entry instead of writing the message string directly into the annotation value.

In the code, it looks like this:
```
@NotNull(message = "{msg://hr_Person.name.validation.NotNull}")
@Column(name = "NAME", nullable = false, unique = true)
private String name;
```

Translation resource files for entities should be in the same package as entities. So, if we want to simplify loading property values, we need to specify the package name in this line. The action is simple, the update algorithm is clear, so it was decided to use code generation.

CUBA Platform plugin transforms the message reference above into the format:

```
@NotNull(message = "{msg://com.company.hr/hr_Person.name.validation.NotNull}")
@Column(name = "NAME", nullable = false, unique = true)
private String name;
```
And now we have the package name, therefore, fetching the message from the resource file using `getResourceAsStream()` method is much simpler.

## What is the Future?
There is not too much code generated at the moment, but the framework is evolving. The development team is thinking about using code generation for other cases.

### Common Entity Methods
At the moment, in CUBA the entity structure is flexible, but it is based on interfaces, so you need to implement methods defined in those interfaces. For example, if you want your entity to support soft delete, you need to implement the following interface:

```
public interface SoftDelete {
   Date getDeleteTs();
   String getDeletedBy();
   //More methods here
}

```
Of course, there are default implementations of those interfaces like `com.haulmont.cuba.core.entity.StandardEntity`, so you can extend this entity in order to use the implementation. 

But it would be much simpler to use method names that are not hardcoded and just mark properties that you want to use to store the delete date and a username of who performed the delete. In this case, we could generate the methods shown above and map invocations to proper getters and setters. Let’s have a look at an example of an entity:

```
@Entity
public class Account {

   //Other fields
   @DeletedDate
   private Date disposedAt;

   @DeletedBy
   private String disposedBy;

   public Date getDisposedAt() {
       return disposedAt;
   }

   public String getDisposedBy() {
       return disposedBy;
   }

}
```
In this entity, you can see special fields defined to store the data about the delete process. So, what will we see if we apply some enhancement to this entity?

```
@Entity
public class Account implements SoftDelete {

   //Other fields
   @DeletedDate
   private Date disposedAt;

   @DeletedBy
   private String disposedBy;

   public Date getDisposedAt() {
       return disposedAt;
   }

   public String getDisposedBy() {
       return disposedBy;
   }

   //Generated
   @Override
   public Date getDeleteTs() {
       return getDisposedAt();
   }

   //Generated
   @Override
   public String getDeletedBy() {
       return getDisposedBy();
   }
}
``` 
Now we can check if the instance supports soft delete by applying the `instanceof` operator, thus implementing a generic approach for soft delete operations within the framework relying only upon the framework’s interfaces and methods instead of detecting annotations in runtime. 

This approach will add more flexibility to entities’ definition, especially in database reverse engineering. 

So, in future CUBA versions, we plan to add more bits and pieces of code generation here and there to make a developer’s life easier. 

## Build-time generation vs runtime generation
As you may notice, in CUBA, code generation happens at build-time. There are pros and cons for this approach, let’s describe them.

Build-time generation allows you to catch problems at earlier stages. When you generate code, there are many “variables” that you should take into account. For example, if EclipseLink API changes, then the invocations generated by CUBA during the enhancement process will become invalid. JDK API changes may cause issues, too. By generating code during build-time we rely on the Java compiler to find such issues at early stages. And compile-time errors are usually easier to find than runtime ones, source code is a static thing. Even if it is generated.

But build-time generation requires a separate tool that is not a part of the project codebase - build plugin. Introducing one more tool means introducing one more point of failure. A developer now depends on a compiler and code generation tool. And if any of them will contain a bug - there is a problem, because a developer cannot update them.

In runtime, there is no separate tool, so a code generator is part of the framework. But generation happens at runtime and developers depend on the program state and the VM state. Sometimes dynamic code generation may fail suddenly due to memory consumption or other issues because it is quite hard to control the VM state completely. 

So, for CUBA we've chosen code generation at build-time. The amount of generated code is not that huge, the set of classes is limited to entities only, so for this particular case the code generator was pretty simple and there were no blocking issues with it so far.

## Generation tools
In Java, a standardized code generation approach appeared starting from Java 5, and it was annotation processing. The idea is simple - you create a processor that can generate new code based on the annotations in the existing code. And you can generate code with annotations that may trigger another processing cycle. 

Standard annotation processor has a limitation - it cannot update the existing code, just generate a new one. So, for CUBA, a Javassist library was used. 

This library allows existing code updates, and it can use plain strings. For example, this code stores the previous value of the property before a setter invocation:
```
ctMethod.insertBefore(
       "__prev = this." + getterName + "();"
);
```
Javassist contains its own limited Java compiler to verify code correctness. Using strings for code generation doesn’t provide type safety, so some bugs can be introduced due to a mistype. But it is much simpler than using a library that uses a typed model for the code generation like ByteBuddy. You literally can see the code that will be added to your classes.  

## Conclusion
Code generation is a very powerful tool that helps developers to:
1. Avoid doing boring jobs like writing simple repetitive code
2. Automate some methods update due to code changes

On the other side, your program is not what you wrote. Extensive code generation can change your sources completely, so you’ll have to debug not your code, but someone else’s. 

In addition to that, you become dependent on the framework’s code generators, and in case of bugs, you have to wait for the plugin update. 

In CUBA, code generation areas are limited to entities, and we plan to extend this area slowly to simplify developers' work and add more flexibility to the framework.

So, if you’re planning to create your own framework or introduce a code generator for the existing one, consider this technique as very powerful, but fragile. Try to generate simple code and document all the generation steps and conditions, because any change in any API may break the generation easily.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Platform Helping IT Education]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-helping-it-education</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-helping-it-education</guid>
            <pubDate>Mon, 12 Oct 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/4b6b970fc26144499d312664f4dbe5c0.jpg">CUBA is modern, productive and easy-to-learn - probably that’s why more than 40 universities all over the world use it for teaching enterprise computing.]]></description>
            <content:encoded><![CDATA[![text]({{strapiUrl}}/uploads/05d4102ee38542e090e8268981a9057d.png)

When CUBA Platform started its way in the world of enterprise development tools, the first users were enthusiasts who gained no profit from spreading the word about CUBA all over. With the community growth, we watched CUBA becoming a popular tool. In 2016 CUBA Platform went open-source and experienced a great rise. Сontinuous community growth and Java professionals acknowledgment showed that the framework has a confident future. 

But we all know, the world is desperately short of software developers! So, since the start we offered free CUBA licenses to academic organizations to help them on their mission. For instance, for several years we’ve been providing free academic subscriptions. Not long ago we made the request process even easier. Today it is possible to request an academic subscription both for students and teachers in a few mouse clicks on the <a href="https://www.cuba-platform.com/store/#/store/studio">CUBA website</a>. 

![text]({{strapiUrl}}/uploads/a8f2b02361bb430c91e87dbead7faca0.png)

CUBA is modern, productive and easy-to-learn - probably that’s why more than 40 universities all over the world use it for teaching enterprise computing, including <a href="https://www.fernuni-hagen.de/" target="_blank">University of Hagen (FernUniversität)</a>, <a href="https://www.qut.edu.au/" target="_blank">Queensland University of Technology</a>, <a href="https://uci.edu/" target="_blank">University of California, Irvine</a>, <a href="http://www.nus.edu.sg/" target="_blank">National University of Singapore</a>, <a href="http://pirogov-university.com/" target="_blank">Pirogov Medical University</a> and others. 

For the last 2 years we provided more than 200 academic license keys. Recently we received a request for academic subscriptions for a whole cohort of students. One of the <a href="http://suinformatics.com" target="_blank">Stellenbosch University</a> professors, Mr <a href="http://suinformatics.com/staff/" target="_blank">Richard Barnett</a>, dedicated a full course to software development and low-code environments, particularly Java frameworks. He has chosen CUBA Studio for practical lessons. 

Stellenbosch is the oldest university in South Africa. It is famous for designing and manufacturing Africa's first microsatellite, SUNSAT, launched in 1999. Richard Barnett’s course is designed for postgraduates getting the Honors degree - it traditionally follows the bachelor’s degree in South Africa. Mr. Barnett’s postgraduates get education in the field of Information Systems Management. They prepare to work as business analysts. The educational program has a focus on designing enterprise systems, so that the graduates could be good at system analysis and working with databases.

The course covers the essentials of building enterprise applications on Java and forms programming and analytical skills. Almost half of it focuses on Java and CUBA Platform. “I saw an ad on Twitter, and went to CUBA website. I understood that CUBA is the best fit to study enterprise applications development in Java. It’s great that the team provides academic licenses for free.The students can program with a real widely used tool,” commented Mr. Barnett. The students will make their final projects on CUBA as well.

We also asked Mr. Barnett what made him choose CUBA. Here’s his answer: “I chose CUBA Platform because it is easy to start making a working application on it. The development process is comfortable and the technology stack is modern. Java is now popular for enterprise development in Johannesburg, you know.” Also, the professor’s aim was to find a framework with a low code environment which concentrates on enterprise applications. He is going to use this educational program and CUBA in the future, too.

That was encouraging news for the team - we hope that in a couple of years these students will use CUBA in real applications and bring value to South African businesses. We are also grateful to Mr. Richard Barnett for sharing his feedback and experience with us, and wish him and his students luck with studying at such a challenging time. 

Take care and do not hesitate to request an academic license for your own course or project!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Development in an Isolated Environment - How to Manage Dependencies?]]></title>
            <link>https://www.jmix.io/cuba-blog/development-in-isolated-network</link>
            <guid>https://www.jmix.io/cuba-blog/development-in-isolated-network</guid>
            <pubDate>Wed, 16 Sep 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/f12d77fb869f4ee48e27faae2f82178b.jpg">How to build an actual stack of frameworks and libraries for a comfortable development process if you’re working remotely in a distant village, flying for 8 hours on a plane, or if the access to the world wide network in your company is so limited that you can’t use public artifact repositories, such as maven central? ]]></description>
            <content:encoded><![CDATA[How to build an actual stack of frameworks and libraries for a comfortable development process if you’re working remotely in a distant village, flying for 8 hours on a plane, or if the access to the world wide network in your company is so limited that you can’t use public artifact repositories, such as maven central? How can we deliver all the necessary artifacts we depend on, including transitive dependencies? How to update them with the new framework versions?

Let’s try to find answers to these questions. In this article I’ll tell you about CUBA SDK - a command line tool which provides an ability to resolve all transitive dependencies for Maven libraries and manage them in remote repositories. Also, we’ll overview the example which can help you use our best practice for any Java application using Maven dependencies.

As you know, our team is working on CUBA - Open Source Java framework for enterprise development. CUBA Platform is a whole ecosystem consisting of the framework and various add-ons that provide extra functionality. And this functionality is ready to use within several clicks.  For the last few years the framework gained huge popularity. Now it’s used by more than 20 000 developers worldwide. With the growth of popularity we met lots of interesting cases. This article will dwell on one of them. Probably, it could help with your project, especially if you work in a company which has a strict security system. 

## Loading Transitive Dependencies to Internal Repositories 

Almost any modern JVM project using Apache Maven or Gradle as a build tool has a big number of transitive dependencies for each of the i library and/or framework being used. With a shared repository accessible by the network, these dependencies are resolved automatically by a dependency manager. 

But what shall we do in case public repositories are inaccessible from the internal network? 

## Solution Options 

The solution may seem simple - we just take Nexus and proxy the access to repositories through it. Indeed, in most cases this will work, but not if you have extra strict security requirements. You can face them in companies of specific types: military, finance, ministries and other government authorities. Access to the internet in such companies is strictly regulated and usually does not allow traditional proxying. 

What shall we do? 

- Option 0. Begging the security team.
- Option 1. Gateway.
- Option 2. Manual dependency management.

Option 0 is not taken into account, let’s consider options 1 and 2. 

The gateway option implies that a company has a gateway computer which can be connected either to external or to internal network. After loading and checking the necessary libraries from the external network, the gateway switches to the internal network, and only after that the libraries are loaded to the internal repositories. Adding new dependencies or updating the existing ones for a single project usually takes a lot of time, as you must get access to the gateway, load the necessary artifacts, check that all transitive dependencies were loaded correctly, and then check out the dependencies to the internal repository. If there are many projects in the company, the working process may stand idle until the required dependencies become accessible from the internal repositories.

Considering the option with manual dependencies management, every time you update or add components you’ll have to check the library dependencies list and compare it with already loaded libraries. 

As we can see, adding or updating dependencies can be a rather complex process.

If you don’t consider corporate security systems, the repository access problem still exists. For example, a developer is going to work in the isolated countryside where the internet connection is weak. To prepare for such a case you can always try offline plugins for Gradle or Maven. But if you have several projects, for each of them you’ll have to 
- configure an offline plugin
- add to the project all potentially useful dependencies so that offline plugins could add them to the dependencies cache correctly, just in case 
- download all the dependencies to the local folder

Which is not quite comfortable, as the project could be overloaded with dependencies and configurations that you’ll have to keep in mind and delete from the project later. And even with all that we still have the problem with creating a new project cause it can lack the necessary modules. 

So what do we offer to solve those problems?

## CUBA SDK

Among CUBA Platform users there are companies which limit or restrict access to the external network for security reasons.

We decided to make the users’ life easier and make a command line tool CUBA SDK which could resolve all dependencies for CUBA Platform, add-ons and any other libraries which have maven coordinates. 

So what’s the difference between CUBA SDK and offline plugins for Gradle or Maven? 
The main difference is that CUBA SDK doesn’t cache the particular project dependencies. It allows you to synchronize artifacts between internal and external repositories, so that the development process in an isolated environment was comfortable.
CUBA SDK doesn’t require a project, so it is possible to create a required offline stack of frameworks, add-ons and libraries with all dependencies. 

Developers can find it useful if they work on several projects or plan a new one and therefore don’t know which modules will be used in the project. With the help of SDK these modules can be loaded to the local or internal repository in advance. 

The companies can profit from SDK by using it for the centralized internal repositories synchronization.

![text]({{strapiUrl}}/uploads/1adb8139fa824006b127a36c4c176fd8.png)

CUBA SDK provides an ability to resolve, export and upload to external repositories all dependencies for CUBA framework, add-ons or any external library with a few simple commands. For completely isolated networks you can use import and export commands or install CUBA SDK on the gateway.

CUBA SDK advantages:

- automatically collects all dependencies with the source code for the loaded libraries 
- resolves dependencies for CUBA Platform and add-ons
- checks for new libraries versions and installs them
- can work with several repositories at a time for artifacts search including local maven repositories
- has an embedded repository Nexus OSS 
- provides an ability to upload artifacts to several repositories at a time including local maven repositories 
- imports and exports artifacts with all dependencies
- provides an interactive mode with prompts for installing CUBA Platform and add-ons
- uses Gradle tools for resolving dependencies
- is IDE-Agnostic 
- can be installed on CI server

## SDK Commands

The full list of available commands can be found on the <a href="https://github.com/cuba-platform/cuba-sdk" target="_blank">GitHub</a>.

CUBA SDK originally supports three component types: CUBA Framework, CUBA add-on and a library that can be loaded through maven coordinates. This list can be expanded for other component types  via CUBA SDK plugins. 

You can install a component to a remote repository via the **install** command. When creating SDK we have foreseen that SDK might be installed on a gateway machine or on a portable device. In this case the components installation is possible via **resolve** and **push** commands.

**resolve** - just resolves and downloads all dependencies to your local SDK cache
**push** - passes the loaded artifacts with their dependencies to the set target repositories

For working with repositories SDK has an embedded repository manager.

The repository manager supports local and remote repositories which are divided into two groups within SDK 
- **source** - repositories used for searching artifacts
- **target** - repositories to which the artifacts will be loaded

SDK itself can be used as a repository. Using the command **setup-nexus** SDK downloads, installs and configures Nexus OSS repository. For launching and stopping the repository use start and stop commands.

For checking and installing updates just run the command **check-updates**. 

## Resolving dependencies

The main problem that the SDK is intended to solve is the correct resolving and collection of dependencies for the components. During the development process we tried several approaches to resolving components’ transitive dependencies. Initially we had an idea that we can just parse the .pom files and compose a dependency tree. But actually, manual dependency parsing wasn’t a good idea, especially since Apache Maven can do it out-of-the-box. 

## Maven as Dependency Manager

So, we took Apache Maven as a tool for transitive dependencies management.

To achieve this CUBA SDK loads maven distributive to the SDK home folder and runs commands via Java Runtime.

For example, the command 
```
dependency:resolve -Dtransitive=true -DincludeParents=true -DoverWriteSnapshots=true -Dclassifier=<classifier> -f pom.xml
```

helped us to resolve all the components’ transitive dependencies described in pom.xml, and those components were automatically loaded to the local maven cash. After that we run the command
```
org.apache.maven.plugins:maven-deploy-plugin:3.0.0-M1:deploy-file -Durl=<repository URL>
```
which loaded the artifacts to the required repository.

The following command lets us load the library to the local repository.
```
org.apache.maven.plugins:maven-dependency-plugin:3.1.1:get -Dartifact=<maven coordinates>
```
For running Maven commands in the CUBA SDK application, we’ve generated the settings.xml file. It contains the list of all repositories that must be used for fetching and loading artifacts. 

## Gradle as Dependency Manager

In the first application version the dependencies resolved correctly but rather slowly, and while testing we got collisions when resolving dependencies for some CUBA Platform add-ons. However, there were no such problems during project build with Gradle. 

So we decided to switch the dependency resolving logic to Gradle. In order to do this we created a build.gradle script with the tasks required for loading and resolving the components dependencies.

For calling Gradle tasks we used Gradle Tooling API. 

To define the dependency path through Gradle we used artifact resolution query API. The following code helped us get the path to the library source:
```
 def component = project.dependencies.createArtifactResolutionQuery()
            .forComponents(artifact.id.componentIdentifier)
            .withArtifacts(JvmLibrary, SourcesArtifact)
            .execute()
            .resolvedComponents[0]
 def sourceFile = component?.getArtifacts(SourcesArtifact)[0]?.file
```
Thus, we got the paths to all files in the local Gradle cache and saved them to the SDK storage. 

To resolve and load dependencies for the components to the local cache we add the components to the configuration and get all dependencies using  `lenientConfiguration`. 
```
project.ext.properties["toResolve"].tokenize(';').each {
            dependencies.add 'extraLibs', it
        }
        def resolved = [:]
        configurations.all.collect {
            if (it.canBeResolved) {
                it.resolvedConfiguration.lenientConfiguration.artifacts.each { art ->
                    try {
                        ...
                    } catch (e) {
                        logger.error("Error: " + e.getMessage(), e)
                        logger.error("could not find pom for {}", art.file)
                    }
                }
            }
        }
```        
We use  `lenientConfiguration` to prevent Gradle script from crashing in case the component can’t be found in the repositories.

For loading artifacts to the repositories SDK runs the `PublishToMavenRepository` Gradle task.
```
task publishArtifact(type: PublishToMavenRepository) {
    doLast {
        if (project.ext.hasProperty("toUpload")) {
            def toUpload = new JsonSlurper().parseText(project.ext.properties["toUpload"])
            def descriptors = new JsonSlurper().parseText(project.ext.properties["descriptors"])

            artifactId toUpload.artifactId
            groupId toUpload.groupId
            version toUpload.version
            descriptors.each { descriptor ->
                artifact(descriptor.filePath) {
                    classifier descriptor.classifier.type
                    extension descriptor.classifier.extenstion
                }
            }
        }
    }
}
```
Thanks to  Gradle we avoid the collisions while resolving transitive dependencies and significantly speed up the application operation. 

## Project Build

For building CUBA SDK we used the same approach as for CUBA CLI. With the jlink tool we built all the necessary modules to bundle them with a  custom JRE delivered together with the application. This approach made SDK independent from the installed Java version. You can find an example of such a build in the <a href="https://github.com/cuba-platform/cli-core-sample" target="_blank">CLI Core Sample project</a>. 

## Third-party Plugins Support

Since CUBA SDK is based on the <a href="https://github.com/cuba-platform/cli-core" target="_blank">CLI Core library</a>, it supports third-party plugins. At the moment, SDK has maven and gradle components dependency managers and providers for CUBA components implemented via third-party plugins.

Let’s have a look at the example of how we can extend the SDK functionality with a plugin. We’ll create a provider for Spring Boot starters from the widely known <a href="https://start.spring.io/" target="_blank">Spring Initializr</a>.

First let’s create a new project. As an example we’ll use the CUBA CLI plugin, as it’s described <a href="https://github.com/cuba-platform/cuba-cli/wiki/Plugin-Development" target="_blank">here</a>, and add the dependencies:
```
implementation "com.haulmont.cli.core:cli-core:1.0.0"
implementation "com.haulmont.cli.sdk:cuba-sdk:1.0.1"
```
Create a new provider for spring boot starters - SpringBootProvider, which extends BintraySearchComponentProvider. BintraySearchComponentProvider enables automatic search of  accessible component versions using the Bintray API.
```
class SpringBootProvider : BintraySearchComponentProvider() {
   var springComponentsInfo: SpringComponentsInfo? = null

   override fun getType() = "boot-starter"
   override fun getName() = "Spring boot starter"

 ...

   override fun load() {
       springComponentsInfo = Gson().fromJson(readSpringFile(), SpringComponentsInfo::class.java)
   }

   private fun readSpringFile(): String {
       return SpringComponentsPlugin::class.java.getResourceAsStream("spring-components.json")
           .bufferedReader()
           .use { it.readText() }
   }
```

This provider will search for the accessible components from spring-components.json file which is the <a href="https://github.com/spring-io/start.spring.io/blob/5294926a91392c12cc709f481c3a1df9650d5747/start-site/src/main/resources/application.yml" target="_blank">json version of yml file in Spring Initializr application</a>. 

For mapping from  json to objects let’s create simple data classes: 
```
data class SpringComponent(
   val name: String,
   val id: String,
   val groupId: String?,
   val artifactId: String?,
   val description: String?,
   val starter: Boolean? = true
)

data class SpringComponentCategory(
   val name: String,
   val content: List<SpringComponent>
)

data class SpringInitializr(
   val dependencies: List<SpringComponentCategory>
)

data class SpringComponentsInfo(
   val initializr: SpringInitializr
)
```
To add this provider to other SDK providers we need to register the provider in the init event of the plugin:
```
class SpringBootComponentsPlugin : CliPlugin {
   private val componentRegistry: ComponentRegistry by sdkKodein.instance<ComponentRegistry>()

   @Subscribe
   fun onInit(event: InitPluginEvent) {
       val bootProvider = SpringBootProvider()
       componentRegistry.addProviders(bootProvider)
       bootProvider.load()
   }

}
```

And that’s it. Now, to install the plugin through the terminal or IDE, run the *gradle installPlugin* command.

Run SDK
![text]({{strapiUrl}}/uploads/83754cff3c7440a7ad4ad3b5bb34572a.png)

We can see that our plugin was successfully loaded. Now let’s check that our logic operates with the help of *resolve boot-starter* command:
![text]({{strapiUrl}}/uploads/5eac281fa5b342679ce4cbe129461f79.png)

![text]({{strapiUrl}}/uploads/5c09660756d0414591f2fa0a26ff2df8.png)

As we can see, the prompts for components and their versions work as they should.

If you store artifacts and dependencies in the storage not the same way as in maven repositories, then you can use plugins to implement your own *ArtifactManager* interface, which can contain the logic for working with your storage.

The test plugin source code can be found on the <a href="https://github.com/cuba-platform/cuba-sdk-spring-boot-plugin" target="_blank">GitHub page</a>.
 
## Conclusion

First of all, CUBA SDK will be useful for companies which have limited access to the external network due to the security requirements. 

If we abstract from companies’ security policy, repositories availability problem is also important for developers, for example, if a developer is going to work alone in the countryside and has poor internet connection there. In this case CUBA SDK is a great choice that will help you to build up an efficient stack of libraries and frameworks locally, on your personal computer.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Multitenancy in CUBA with Citus]]></title>
            <link>https://www.jmix.io/cuba-blog/multitenancy-in-cuba-with-citus</link>
            <guid>https://www.jmix.io/cuba-blog/multitenancy-in-cuba-with-citus</guid>
            <pubDate>Mon, 08 Jun 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/da6f3782298c4cc0a00cb38baba7d182.jpg">Multitenancy is a reference to the mode of operation of software where multiple independent instances of one or multiple applications operate in a shared environment. The instances (tenants) are logically isolated, but physically integrated. ]]></description>
            <content:encoded><![CDATA[## Introduction

Multitenancy is a reference to the mode of operation of software where multiple independent instances of one or multiple applications operate in a shared environment. The instances (tenants) are logically isolated, but physically integrated. 

You can find a nice explanation on the Internet where the multi-tenant approach is compared to office building leasing:

*Apartments are a perfect example of a multi-tenant architecture. They have a centralized administration for security (at the main gate), electricity, water, and other facilities. These facilities are owned by the apartment owner and shared by the tenants.*

In this article, we will reason about the multi-tenancy architecture and review one of the implementations of this approach in CUBA Platform.

## A Short History of Multi-Tenancy

Let us start from a completely different topic - software distribution and deployment. Initially software was distributed using physical media - tapes, discs, flash drives. And usually you had to deploy the software to the server that was installed in the local network. Communication channels back those days were not as good as they are now.

But gradually the internet bandwidth grew up, and now we’re talking about megabit- and gigabit-wide channels. So, it became much easier to deliver software via the internet - downloading a hundred megabytes takes less time than going to a store to buy a DVD or a Blu-ray disc with the software. 

Meanwhile, communication channels and computing hardware development caused a new market to emerge - virtualization, and later - IaaS (infrastructure as a service). It became easier to set up a server with a pre-installed software product and give access to users. 
As a result, vendors adopted SaaS - “software-as-a-service” distribution model. You, as a client, just had to buy access to a software product deployed. You didn’t need to maintain local servers, so TCO was lower.

Installing a software instance for each client was still not an easy operation, so software developers started to use the multi-tenant architecture to simplify deployment and maintenance. You still can see a lot of SaaS deployments on the internet. For example, Salesforce started using a multi-tenant approach and SaaS distribution a long time ago.
But implementing multi-tenant applications is a challenging task. You have to think about separating customer’s data, cooperative resource consumption, common data sharing and other things. The latest respone to these challenges is the PaaS (platform-as-a-service) model. 

Containerization and DevOps processes development are the main threats for multi-tenant applications. Today it is very easy to start a new “server” or even a whole “infrastructure”, including database, application services, caching servers and reverse proxy, thanks to such products as Docker and Kubernetes. For developers, it is much simpler to implement a single-tenant application and then deploy a new instance of it for every new client, literally, in seconds and even happens in a fully automated way. Sometimes it might lead to another phenomenon called “<a href="https://www.infoq.com/presentations/multi-tenancy-kubernetes/" target="_blank">cube sprawl</a>” though, but there is no “silver bullet” in this world.  

Nevertheless, multi-tenant applications are still a big deal as for today (see Salesforce, Work Day, Sumo Logic, etc.), and still, there is a request for developing such products. Let’s review some approaches to implementing multi-tenancy and then see what CUBA Platform can offer in this area.   

## Multi-tenancy implementations

There are three main multi-tenancy model types applied to building a multi-tenant datastore:
  
 <br>
 <img src="{{strapiUrl}}/uploads/be0139222d3f4ee39baca047cedf227c.png" style="float: right; height: 180px; margin-left:35px;margin-bottom:20px;">
1. Single shared database. Tenants’ data is stored in the same schema and share the same tables. To separate data from different tenants, a developer introduces a discriminator column that stores the tenant’s identifier. It means that we isolate data separated on the query level. An application implicitly adds a predicate for every query statement, therefore, there is no way to select other tenant’s data. 
This is a simple and cost-effective way to implement multi-tenancy architecture. It is also easy to maintain - you need to update only one instance of the application. However, there might be some concerns regarding data security. If you have an error in your SQL, you can accidentally expose data from other tenants. 

<br style="clear:both;">
<br> 
<img src="{{strapiUrl}}/uploads/b2096b52ad9a4808af5ba9d938880916.png" style="float: right; height: 180px;margin-left:35px;margin-bottom:20px;">
2. The second approach is to use multiple database schemas for different tenants, the application instance still remains shared. It is a valuable architecture when data from different tenants need to be treated differently -- such as if they had to go through different geographic regulations. But at the same time you are able to share some common data between tenants to avoid duplications. To implement this architecture, you’ll have to use some routing mechanism to redirect queries to different schemas. For example, in the Spring Framework framework you can find a RoutingDataSource class implemented exactly for this purpose.

<br style="clear:both;">
<br>
<img src="{{strapiUrl}}/uploads/aa252517ca5a4524b70d21b24f73c53d.png" style="float: right; width: 150px;margin-left:35px; margin-bottom:20px;">
3. The third type of multi-tenant architecture hosts data in multiple databases. It also uses a routing mechanism, but we redirect queries between different databases, not schemas. This model is relatively complex in terms of management and maintenance. When the application is updated, you need to update all the databases. Updating the database version is also going to be an interesting task, especially if you have a lot of tenants. 
On the other hand, tenants are separated by a chosen criterion and the risk of accessing someone else’s data and consuming other application’s resources is at the lowest level. Also, this approach provides good scalability possibilities, you can scale data storage individually based on each tenant’s requirements.
<br style="clear:both;">
 <br>

**Advantages and disadvantages of multi-tenancy**
There are a number of pros and cons for the multi-tenant architecture:

Pros:
1. Costs. It is usually less expensive compared to other solutions.
2. Simplified maintenance - administrators should monitor, patch, upgrade, and tune only one system.
3. Easily scalable - adding a new tenant is a standardized, quick, and simple process.

Cons:
1. Creating a multi-tenant application is a more complex task compared to a single-tenant one.
2. Flexibility might be an issue, especially for applications shared by customers from different counties. There may be different requirements for personal data protection, business logic calculation, etc.
3. “Nosy neighbor” problem. Another tenant may access your data or consume your resources.
4. And the “single point of failure” problem. If all clients share the same resource (e.g. database), all of them are affected if this resource becomes unavailable. 

## Multitenancy in CUBA

CUBA framework allows us to change generated queries to the database on the fly, that’s how row-based security is implemented. And it was pretty easy to extend this mechanism for multi-tenancy applications support and implement an add-on.

When you implement a multi-tenant application using CUBA, you need to decide which entities will store tenant-specific data. As an example, let’s take the <a href="https://demo10.cuba-platform.com/petclinic/#login" target="_blank">“PetClinic” sample application</a>. The data model for the application is represented in the diagram below.

![text]({{strapiUrl}}/uploads/85af16bf471844e4adf96adc8693a4a2.jpg)

You can make all entities tenant-specific, but there is another option - make some reference entities shared. We can say that veterinarian specialties and pet types are “safe” in terms of sharing between different clients. We can tell the same about some other “common” data, e.g. list of countries in the world, etc. This will allow us to save some space and ensure that “standard” data will remain the same for all tenants, so we can rely on it when implementing the business logic. 

If you want your entity to support multi-tenancy in CUBA, you need to implement a special interface - `com.haulmont.cuba.core.entity.TenantEntity`. After that, the add-on will take the special column for tenant separation into account. For example, here is the code fragment form Pet entity:
```
public class Pet extends NamedEntity implements TenantEntity {
   
   @TenantId
   @Column(name = "TENANT_ID")

   protected String tenantId;
   @NotNull
   @Column(name = "IDENTIFICATION_NUMBER", nullable = false)
   protected String identificationNumber;

   @OneToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "TYPE_ID")
   protected PetType petType;
```
Please note that all “system” CUBA entities support multi-tenancy by default. So you will get all users, roles, saved filters, security groups, etc. separated for each client. 

After entities are created, CUBA will add an extra condition “where tenant_id = <tenant>” for all JPQL queries (including joins) that are generated for multi-tenant entities. For application developers, this approach is mostly transparent unless they want to use native SQL. In this case, they need to explicitly add the additional condition to their queries to prevent data leaks. 

For example, if we want to select pets and owners from the petclinic database, the final query will look like this:
```
SELECT *
FROM PETCLINIC_PET t1
        LEFT OUTER JOIN PETCLINIC_OWNER t0
                        ON ((t0.ID = t1.OWNER_ID)
                       AND (t0.TENANT_ID = t1.TENANT_ID))
        LEFT OUTER JOIN PETCLINIC_PET_TYPE t2
                        ON (t2.ID = t1.TYPE_ID)
WHERE ((t1.TENANT_ID = 'clinic_one') AND (t1.DELETE_TS IS NULL))
```
Please note the following conditions in the query: **`AND (t0.TENANT_ID = t1.TENANT_ID))`** and **`(t1.TENANT_ID = 'clinic_one')`**. Those are conditions that CUBA adds implicitly.

But is there a way to transparently apply multi-tenancy on the database level in addition to the application level? One of the answers is <a href="https://www.citusdata.com/" target="_blank">Citus</a>.

## Citus: multi-tenancy for PostgreSQL 

As it is said in the <a href="https://docs.citusdata.com/en/v9.3/get_started/what_is_citus.html" target="_blank">description</a>: “Citus is basically worry-free Postgres that is built to scale out. It’s an extension to Postgres that distributes data and queries in a cluster of multiple machines. As an extension (rather than a fork), Citus supports new PostgreSQL releases, allowing users to benefit from new features while maintaining compatibility with existing PostgreSQL tools.

Citus horizontally scales PostgreSQL across multiple machines using sharding and replication. Its query engine parallelizes incoming SQL queries across these servers to enable human real-time (less than a second) responses on large datasets.”

And it looks like Citus resolves a lot of challenges connected with creating multi-tenant applications. It allows us to use the approach “separate database per tenant” and it “looks” like a single database for the application. All the queries are modified according to rules defined during Citus cluster creation. 

It means that you can use CUBA multi-tenant implementation and get physically separated databases without rewriting queries. Let’s have a closer look at the Citus database creation process.

First, you need to create a database cluster and add nodes to it. The cluster consists of the coordinator node and worker nodes. Each worker node stores tenant-specific data, and the coordinator will reroute queries according to the “tenant_id” column. The application sends queries to the coordinator only. The process is on the picture below (taken from the Citus DB documentation):

![text]({{strapiUrl}}/uploads/381851d1da3e4d4b99e4a192a4f06731.jpg)

Also, to work with Citus, you need to define table types during database creation. There are three of them:
1. Distributed. Those are the tables partitioned between worker nodes. They contain tenant-specific data.
2. Reference tables - tables that store information that can be used by all tenants. As for the PetClinic example - those will be “Specialty” and “Pet Type”.
3. Local tables. Service tables that are not used in join queries with distributed or reference tables. As an example - Cituses’ own metadata tables stored on the coordinator node.

Enterprise version of Citus allows separating tenant’s data explicitly by assigning the following operator: 
```
SELECT isolate_tenant_to_new_shard('table_name', 'tenant_id');
```
And this will replace hash-based partitioning that is used by default. 

## Using Citus with CUBA

For the CUBA application, we don’t need to rewrite the application’s code, but the database and table creation process should be modified to be “Citus-compatible”. We all love CUBA for its SQL generation magic, but unfortunately, you have to create some scripts manually to support Citus. 

The database creation process is changed. You need to create Citus extension, add nodes, and enable replication:
```
CREATE EXTENSION citus;

SELECT * from master_add_node('localhost', 9701);
SELECT * from master_add_node('localhost', 9702);

SET citus.replication_model = 'streaming';
 ```
The good thing is that you can develop an application on the local “ordinary” PostgreSQL most of the time and add Citus-specific table creation scripts only before deploying to the staging or production (if you are brave enough not to use staging) environment. The only thing that changes is the database address - instead of the dev local database, you need to specify the Citus cluster coordinator database address. 

As for the database creation and update, you need to specify distributed tables explicitly (table name and partition column) like this:
```
SELECT create_distributed_table('petclinic_vet', 'tenant_id');
SELECT create_distributed_table('petclinic_owner', 'tenant_id');
SELECT create_distributed_table('petclinic_pet', 'tenant_id');
SELECT create_distributed_table('petclinic_visit', 'tenant_id');
```
And a similar process should be applied for the reference tables: 
```
SELECT create_reference_table('petclinic_specialty');
SELECT create_reference_table('petclinic_vet_specialty_link');
SELECT create_reference_table('petclinic_pet_type');
```
In order to improve performance, you can add table <a href="https://docs.citusdata.com/en/v9.3/sharding/data_modeling.html#colocation" target="_blank">colocation</a> in addition to partitioning. But from the CUBA side - you don’t need to change anything, multi-tenancy is an absolutely transparent process. 

That’s it. With the minimum efforts, we can scale the PetClinic application horizontally and use multi-tenancy on the database level, too. All the complexity is hidden in the framework and Citus plugin.

## Conclusion
 
Creating multi-tenant applications might be a challenging job. You should consider all options before starting implementing such an approach. And technology is only one part of the equation: you need to consider license costs, cloud services tariffs, maintainability, scalability, etc. Nowadays, the PaaS model along with containerization and proper DevOps processes looks more appealing than “traditional” multi-tenant architecture, but demand on such applications is still noticeable. 

If you decide to go forward with multi-tenancy, ensure that your application meets all security requirements, e.g. GDPR, HIPAA, etc. Some of them may explicitly prohibit storing data in the same database, so you’ll need to use a “separate database” approach to satisfy those requirements.

And remember that tools matter. Proper development frameworks and data management systems that support multi-tenancy architecture out of the box may greatly simplify development and prevent a lot of typical issues connected with multi-tenancy architecture.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ Helium - New Theme for CUBA Applications]]></title>
            <link>https://www.jmix.io/cuba-blog/helium-announce</link>
            <guid>https://www.jmix.io/cuba-blog/helium-announce</guid>
            <pubDate>Mon, 20 Apr 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/2853cf2fae5241c5b5c9c89225759875.png">We are happy to present our new visual theme - Helium! Helium is much cleaner and brighter with less visual noise comparing to its predecessors. Theme comes with editor which allows to rapidly create custom color presets.]]></description>
            <content:encoded><![CDATA[CUBA has always kept its target at business applications development. Business applications commonly introduce user interface for the back-office staff, where the most important part is how functional it is. For many years the look and feel was not the main subject for the back-office type of UI. Controls were rather compact with the only reason: to fit as many of them as possible into a single screen, making it as functional as possible.

For the last decade, more and more touch-screen devices with the shorter diagonal came into the game. This has changed the rules. Controls should be easy to tap on, having enough spacing in between. Colors go more motley and contrasty. Styling is now at a much higher priority than before, taking a significant part of non-functional requirements to any modern application.

Following the trends, we are happy to present our new visual theme - Helium! Helium is much cleaner and brighter with less visual noise comparing to its predecessors. Another important thing about the new theme is the ability to customize styling with minimal efforts for both end-users and CUBA developers.

## Features

First of all, the new theme is very dynamic, so you can change application styling right on the fly! Previously, CUBA used SCSS variables to define colors and this approach required recompilation every time we change them. The new theme relies on the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties" target="_blank">CSS custom properties</a>, which get applied immediately in runtime, even without page refresh or re-login.

![text]({{strapiUrl}}/uploads/2e15e9fab550420b8933b87477a7a9f4.gif)

### Color Presets
There are two color presets provided out of the box - light and dark.

To manage presets available for end-users modify the following properties in theme.properties (theme installation process is provided in the self-titled section below):

```
cuba.theme.modes = light|dark
cuba.theme.defaultMode = light
```

Also, you can create your own color presets using the online theme editor (more details to follow in the Online Demo and Editor section). 

### Size Presets

There are three built-in presets for size: small, medium and large:

Similarly to the colors presets, you can modify presets for sizes in theme.properties via the following properties:

```
cuba.theme.sizes = small|medium|large
cuba.theme.defaultSize = medium
```
### Settings Screen

The settings screen can be found in the main menu under Help -> Theme Settings. It will help each end-user to personalize their color and size presets. The screen illustrates all major controls, so users can preview how their application will look.

## <a href="https://demo10.cuba-platform.com/helium-editor/" target="_blank">Online Demo and Editor</a>

![text]({{strapiUrl}}/uploads/c4e2f5bda0034208a72a075d1e4e29a3.png)

Another important thing about the new theme is its new interactive editor <a href="https://demo10.cuba-platform.com/helium-editor/" target="_blank">available online</a>. Here you can play around with the available styling variables and see the result right away - once the theme meets your requirements just tap the download button and follow the provided instructions to apply it in your CUBA application.

The best part of the online theme editor is that not only developers can use it. Send this link to your picky customer, so they can customize the colors in accordance with their preference and send the result, which can be applied within a few minutes. The editor itself also allows to import color variables to continue work on a preset.

To apply custom preset you will have to create a <a href="https://doc.cuba-platform.com/studio/#generic_ui_themes">theme extension</a> based on Helium.

## Installation

The theme is distributed as an <a href="https://www.jmix.io/cuba-platform/marketplace/helium/" target="_blank">add-on</a>. The add-on is compatible with CUBA applications starting from version 7.1.5 (note that we always recommend following our bugfix releases and keep your application at the latest one). Find the add-on installation guide in <a href="https://doc.cuba-platform.com/studio/#add_ons" target="_blank">this chapter</a> of the Studio documentation.

Since the add-on is installed you can enable the new theme in the following ways:
Start the application and open the settings screen available under the main menu: Help -> Settings. Pick Helium in the Visual Theme lookup field.
To make Helium available by default add 
```
cuba.web.theme = helium
```
to  `web-app.properties`. 

If you have the custom `cuba.themeConfig` property, do not forget to include the Helium properties: 
```
cuba.themeConfig = +/com/haulmont/addon/helium/web/helium-theme.properties
```

If you want to **customize the theme properties**, create the `helium-theme.properties` file in your main package in the web module with the following content:

```
@include=com/haulmont/addon/helium/web/helium-theme.properties

cuba.theme.modes = light|dark
cuba.theme.defaultMode = light

cuba.theme.sizes = small|medium|large
cuba.theme.defaultSize = medium
```

Also register this properties file in the `cuba.themeConfig` property:

```
cuba.themeConfig = +/com/example/project/helium-theme.properties
```

If there is a need to make **deep customization** including applying custom color preset, you will have to create theme extension. Please use the following <a href="https://github.com/cuba-platform/helium-theme#applying-custom-color-preset" target="_blank">instruction</a>.

## Roadmap

We plan to evolve the Helium theme and introduce new features, including:
* Dark look improvements
* More useful templates in the theme editor
* Auto-switching between light and dark looks
* Customizable border radius variable, also based on CSS variables
* CUBA component kit for Figma. Figma is one of the most trending tools for UI/UХ designers where they create screen mock-ups.

## Conclusion
We hope the new theme and its live editor will be useful for new projects and also for those who wanted to bring a breath of fresh air in their applications. If you have any questions, please create a topic on our <a href="https://www.cuba-platform.com/discuss/" target="_blank">support forum</a>. The source code is available on GitHub: <a href="https://github.com/cuba-platform/helium-theme" target="_blank">theme</a> / <a href="https://github.com/cuba-platform/helium-theme-editor">editor</a>. Looking forward to seeing your feedback!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Platform Italian]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-italian</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-italian</guid>
            <pubDate>Mon, 30 Mar 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/514322a4da2242fa93f0d214820785d0.jpg">CUBA website in Italian launched! All the commercial services including consultancy & support, training and custom development are now available in Italian.]]></description>
            <content:encoded><![CDATA[CUBA Community grows with every day. Developers use CUBA Platform worldwide and create applications for their customers in various countries. 

We already have Russian and Chinese websites. And recently we’ve launched [CUBA website in Italian](https://jmix.it). All the commercial services including consultancy & support, training and custom development are now available in Italian.

We believe that it will be really useful for the community - now it is possible to share experience and get help on the forum in Italian, too!

# CUBA Platform in Italiano

La comunità di CUBA cresce di giorno in giorno. Gli sviluppatori utilizzano la piattaforma CUBA in tutto il mondo e creano applicazioni per i loro clienti in vari paesi.
 
Abbiamo già i siti web tradotti in Russo e Cinese. E recentemente abbiamo lanciato il sito web di CUBA in Italiano. Tutti i servizi commerciali, tra cui la consulenza e il supporto, la formazione e lo sviluppo personalizzato, sono ora disponibili anche in Italiano.
 
Crediamo che sia davvero utile per la comunità - ora è possibile condividere le vostre esperienze con CUBA e ottenere aiuto anche sul forum Italiano!

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA: Getting Ready for Production]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-getting-ready-for-production</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-getting-ready-for-production</guid>
            <pubDate>Wed, 04 Mar 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/a07f0d67b82f44329b5b3cef5e8bfa29.jpg">“It works on my local machine!” Nowadays it sounds like a meme, but the problem “development environment vs production environment” still exists. As a developer, you should always keep in mind that your application will start working in the production environment one day. In this article, we will talk about some CUBA-specific things that will help you to avoid problems when your application will go to production. ]]></description>
            <content:encoded><![CDATA[“It works on my local machine!” Nowadays it sounds like a meme, but the problem “development environment vs production environment” still exists. As a developer, you should always keep in mind that your application will start working in the production environment one day. In this article, we will talk about some CUBA-specific things that will help you to avoid problems when your application will go to production.
 
## Coding Guidelines

### Prefer Services

Almost every CUBA application implements some business logic algorithms. The best practice here is to implement all business logic in CUBA Services. All other classes: screen controllers, application listeners, etc. should delegate business logic execution to services. This approach has the following advantages:

1. There will be only one implementation of the business logic in one place
2. You can call this business logic from different places and expose it as a REST service. 

Please remember that business logic includes conditions, loops, etc. It means that service invocations ideally should be a one-liner. For example, let’s assume that we have the following code in a screen controller:

```java
Item item = itemService.findItem(itemDate);
if (item.isOld()) {
   itemService.doPlanA(item);
} else {
   itemService.doPlanB(item);
}
```
If you see code like this, consider moving it from the screen controller to the ```itemService``` as a separate method ```processOldItem(Date date)``` because it looks like a part of your application’s business logic.  

Since screens and APIs can be developed by different teams, keeping business logic in one place will help you to avoid application behavior inconsistency in production. 

### Be Stateless
When developing a web application, remember that it will be used by multiple users. In the code, it means that some code can be executed by multiple threads at the same time. Almost all application components: services, beans as well as event listeners are affected by multithreading execution. The best practice here is to keep your components stateless. It means that you should not introduce shared mutable class members. Use local variables and keep the session-specific information in the application store that is not shared between users. For example, you can keep a small amount of serializable data in the <a href="https://doc.cuba-platform.com/manual-latest/userSession.html" target="_blank">user session</a>.

If you need to share some data, use the database or a dedicated shared in-memory storage like Redis.

### Use Logging
Sometimes something goes wrong in production. And when it happens, it is quite hard to figure out what exactly caused the failure, you cannot debug the application deployed to prod. To simplify further work for yourself, your fellow developers and support team and to help understand the issue and be able to reproduce it, always add logging to the application. 

In addition, logging plays the passive monitoring role. After application restart, update or reconfiguration an administrator usually looks at logs to make sure that everything has started successfully. 

And logging may help with fixing issues that may happen not in your application, but in the services that your application is integrated with. For instance, to figure out why a payment gateway rejects some transactions, you may need to record all the data and then use it during your talks with the support team. 

CUBA uses a proven package of the slf4j library as a facade and logback implementation. You just need to inject the logging facility to your class code and you’re good to go.
```java
@Inject
private Logger log;
```
Then just invoke this service in your code: 

```java
log.info("Transaction for the customer {} has succeeded at {}", customer, transaction.getDate());
```

Please remember that log messages should be meaningful and contain enough information to understand what has happened in the application.  You can find a lot more logging tips for Java applications in the article series “Clean code, clean logs”. Also, we’d recommend having a look at the <a href="https://dzone.com/articles/9-logging-sins-in-your-java-applications" target="_blank">“9 Logging Sins” article</a>. 

Also, in CUBA we have performance statistics logs, so you can always see how the application consumes a server’s resources. It will be very helpful when customer’s support starts receiving users’ complaints about the application being slow. With this log in hands, you can find the bottleneck faster.

### Handle Exceptions
Exceptions are very important because they provide valuable information when something goes wrong in your application. Therefore, rule number one - never ignore exceptions. Use ```log.error()``` method, create a meaningful message, add context and stack trace. This message will be the only information that you will use to identify what happened.

If you have a code convention, add the error handling rules section into it. 

Let’s consider an example - uploading a user’s profile picture to the application. This profile picture will be saved to the CUBA’s file storage and file upload API service.

This is how you must not deal with an exception:
```java
        try {
            fileUploadingAPI.putFileIntoStorage(uploadField.getFileId(), fd); 
        } catch (Exception e) {}
``` 
If an error occurs, nobody will know about it and users will be surprised when they don’t see their profile picture.

This is a bit better, but far from ideal.
```java
        try {
            fileUploadingAPI.putFileIntoStorage(uploadField.getFileId(), fd); 
        } catch (FileStorageException e) {
            log.error (e.getMessage)
        }
``` 
There will be an error message in logs and we will catch only particular exception classes. But there will be no information about context: what was the file’s name, who tried to upload it. Moreover, there will be no stack trace, so it will be quite hard to find where the exception occurred. And one more thing - a user won’t be notified about the issue.

This might be a good approach.
```java
        try {
            fileUploadingAPI.putFileIntoStorage(uploadField.getFileId(), fd); 
        } catch (FileStorageException e) {
            throw new RuntimeException("Error saving file to FileStorage", e);
        }
``` 
We know the error, do not lose the original exception, add a meaningful message. The calling method will be notified about the exception. We could add the current user name and, probably, the file name to the message to add a bit more context data. This is an example of the CUBA web module. 

In CUBA applications, due to their distributed nature, you might have different exception handling rules for core and web modules. There is a special section in the documentation regarding <a href="https://doc.cuba-platform.com/manual-latest/exception_handling.html" target="_blank">exception handling</a>. Please read it before implementing the policy. 

## Environment Specific Configuration

When developing an application, try to isolate environment-specific parts of the application’s code and then use feature toggling and profiles to switch those parts depending on the environment. 

### Use Appropriate Service Implementations
Any service in CUBA consists of two parts: an interface (service API) and its implementation. Sometimes, the implementation may depend on the deploy environment. As an example, we will use the file storage service. 

In CUBA, you can use a <a href="https://doc.cuba-platform.com/manual-latest/file_storage.html" target="_blank">file storage</a> to save files that have been sent to the application, and then use them in your services. The <a href="https://doc.cuba-platform.com/manual-latest/file_storage_impl.html" target="_blank">default implementation</a> uses the local file system on the server to keep files. 

But when you deploy the application to the production server, this implementation may not work well for cloud environments or for <a href="https://doc.cuba-platform.com/manual-latest/cluster_mw.html" target="_blank">the clustered deployment configuration</a>. 

To enable environment-specific service implementations, CUBA supports <a href="https://doc.cuba-platform.com/manual-7.2/spring_profiles.html" target="_blank">runtime profiles</a> that allow you to use a specific service depending on the startup parameter or the environment variable.

For this case, if we decide to use Amazon S3 implementation of the file storage in production, you can specify the bean in the following way:

```
<beans profile="prod">
   <bean name="cuba_FileStorage" class="com.haulmont.addon.cubaaws.s3.AmazonS3FileStorage"/>
</beans>
```
And S3 implementation will be automatically enabled when you set the property: 

```
spring.profiles.active=prod
```
So, when you develop a CUBA application, try to identify environment-specific services and enable proper implementation for each environment. Try not to write code that looks like this:

```java
If (“prod”.equals(getEnvironment())) {
   executeMethodA();
} else {
   executeMethodB();
}
```
Try to implement a separate service ```myService``` that has one method ```executeMethod()``` and two implementations, then configure it using profiles. After that your code will look like this:

```java
myService.executeMethod();
```
Which is cleaner, simpler and easier to maintain. 

### Externalize Settings
If possible, extract application settings to properties files. If a parameter can change in the future (even if the probability is low), always externalize it. Avoid storing connection URLs, hostnames, etc. as plain strings in the application’s code and never copy-paste them. The cost of changing a hardcoded value in the code is much higher. Mail server address, user’s photo thumbnail size, number of retry attempts if there is no network connection - all of these are examples of properties that you need to externalize.  Use <a href="https://doc.cuba-platform.com/manual-latest/config_interface_usage.html" target="_blank">configuration interfaces</a> and inject them into your classes to fetch configuration values. 

Utilize <a href="https://doc.cuba-platform.com/manual-7.2/spring_profiles.html" target="_blank">runtime profiles</a> to keep environment-specific properties in separate files.

For example, you use a payment gateway in your application. Of course, you should not use real money for testing the functionality during development. Therefore, you have a gateway stub for your local environment, test API on the gateway side for the pre-production test environment and a real gateway for the prod. And gateway addresses are different for these environments, obviously. 

Do not write your code like this:

```java
If (“prod”.equals(getEnvironment())) {
      gatewayHost = “gateway.payments.com”;
} else if (“test”.equals(getEnvironment())) {
      gatewayHost = “testgw.payments.com”;
} else {
      gatewayHost = “localhost”;
}
connectToPaymentsGateway(gatewayHost);
```
Instead, define three properties files: ```dev-app.properties```, ```test-app.properties``` and ```prod-app.properties``` and define three different values for the ```database.host.name``` property in these. 

After that, define a configuration interface:
```java
@Source(type = SourceType.DATABASE)
public interface PaymentGwConfig extends Config {

    @Property("payment.gateway.host.name")
    String getPaymentGwHost();
}
```
Then inject the interface and use it in your code:
```java
@Inject
PaymentGwConfig gwConfig;

//service code

connectToPaymentsGateway(gwConfig.getPaymentGwHost());
```
This code is simpler and does not depend on the environments, all settings are in property files and you should not search for them inside your code if something is changed. 

### Add Network Timeouts Handling
Always consider service invocations via network as unreliable. Most of the current libraries for web service invocations are based on the synchronous blocking communication model. It means that the application pauses until the response is received if you invoke a web service from the main execution thread. 

Even if you execute a web service call in a separate thread, there is a chance that this thread will never resume execution due to a network timeout. 

There are two types of timeouts:
1. Connection timeout
2. Read timeout

In the application, those timeout types should be handled separately. Let’s use the same example as in the previous chapter - a payment gateway. For this case the read timeout might be significantly longer than the connection one. Bank transactions can be processed for quite a long time, tens of seconds, up to several minutes. But connection should be fast, therefore, it is worth setting the connect timeout here up to 10 seconds, for instance.

Timeout values are good candidates to be moved to property files. And always set them for all your services that interact via a network. Below is an example of a service bean definition:

```xml
<bean id="paymentGwConfig" class="com.global.api.serviceConfigs.GatewayConfig">
    <property name="connectionTimeout" value="${xxx.connectionTimeoutMillis}"/>
    <property name="readTimeout" value="${xxx.readTimeoutMillis}"/>
</bean>
```
In your code, you should include a special section that deals with the timeouts. 

## Database Guidelines

A database is a core of almost any application. And when it comes to production deploy and update, it is very important not to break the database. In addition to this, the database workload on a developer’s workstation is obviously different from the production server. That’s why you might want to implement some practices described below. 

### Generate Scripts Specific for the Environment
In CUBA, we generate SQL scripts for both creating and updating the application’s database. And after the first database creation on the production server, as soon as the model changes, the CUBA framework generates update scripts.

There is a <a href="https://doc.cuba-platform.com/manual-latest/db_update_in_prod.html" target="_blank">special section</a> regarding the database update in production, please read it before going to production for the first time.

Final advice: always perform the database backup before updating. This will save you a lot of time and nerves in case of any problem.

### Take Multitenancy into Account
If your project is going to be a <a href="https://www.datamation.com/cloud-computing/what-is-multi-tenant-architecture.html" target="_blank">multi-tenant application</a>, please take it into account at the beginning of the project. 

CUBA supports multitenancy via the <a href="https://github.com/cuba-platform/multitenancy-addon/blob/master/README.md" target="_blank">add-on</a>, it introduces some changes to the application’s <a href="https://github.com/cuba-platform/multitenancy-addon/blob/master/README.md#cuba-system-tenant-specific-entities" target="_blank">data model</a> and the database’s queries logic. As an example, a separate column ```tenantId``` is added to all Tenant-specific entities. Therefore, all queries are implicitly modified to use this column. It means that you should consider this column when writing native SQL queries. 

Please note that adding multi-tenancy capabilities to an application that works in production might be tricky due to the specific features mentioned above. To simplify migration, keep all custom queries in the same application layer, preferably in services or in a separate data access layer. 

## Security Considerations

When it comes to an application that can be accessed by multiple users, security plays an important role. To avoid data leaks, unauthorized access, etc. you need to consider security seriously. Below you can find a couple of principles that will help you to improve the application in terms of safety. 

### Secure Coding
Security starts with the code that prevents issues. You can find a very good reference regarding secure coding provided by Oracle <a href="https://www.oracle.com/technetwork/java/seccodeguide-139067.html" target="_blank">here</a>. Below you can find some (maybe obvious) recommendations from this guide.

**Guideline 3-2 / INJECT-2: Avoid dynamic SQL**

It is well known that dynamically created SQL statements including untrusted input are subject to command injection. In CUBA, you may need to execute JPQL statements, therefore, avoid dynamic JPQL too. If you need to add parameters, use proper classes and statement syntax:
```
       try (Transaction tx = persistence.createTransaction()) {
            // get EntityManager for the current transaction
            EntityManager em = persistence.getEntityManager();
            // create and execute Query
            Query query = em.createQuery(
                    "select sum(o.amount) from sample_Order o where o.customer.id = :customerId");
            query.setParameter("customerId", customerId);
            result = (BigDecimal) query.getFirstResult();
            // commit transaction
            tx.commit();
        }
```
**Guideline 5-1 / INPUT-1: Validate inputs**

Input from untrusted sources must be validated before use. Maliciously crafted inputs may cause problems, whether coming through method arguments or external streams. Some of the examples are overflow of integer values and directory traversal attacks by including "../" sequences in filenames. In CUBA, you can use <a href="https://doc.cuba-platform.com/manual-7.1/gui_validator.html" target="_blank">validators in the GUI</a> in addition to checks in your code. 

Those above are just a few examples of secure coding principles. Please read the guide carefully, it will help you to improve your code in many ways. 

### Keep Personal Data Secured
Some personal information should be protected because it is a law requirement. In Europe we have <a href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation" target="_blank">GDPR</a>, for the medical application in the USA, there are <a href="https://en.wikipedia.org/wiki/Health_Insurance_Portability_and_Accountability_Act" target="_blank">HIPAA</a> requirements, etc. So, take it into consideration when implementing your application. 

CUBA allows you to set various <a href="https://doc.cuba-platform.com/manual-latest/permissions.html" target="_blank">permissions</a> and restrict access to data using roles and access groups. In the latter, you can define various <a href="https://doc.cuba-platform.com/manual-latest/constraints.html" target="_blank">constraints</a> that will allow you to prevent unauthorized access to personal data. 

But providing access is only one part of keeping personal data secured. There are a lot of requirements in data protection standards and industry-specific requirements. Please have a look at these documents before planning the application’s architecture and data model. 

### Alter or Disable Default Users and Roles
When you create an application using CUBA framework, two users are created in the system: ```admin``` and ```anonymous```.  Always change their default passwords in the production environment before the application is available to users. You can do it either manually or add an SQL statement to the ```30-....sql``` initialization script. 

Use recommendations from the <a href="https://doc.cuba-platform.com/manual-7.1/roles_example.html" target="_blank">CUBA documentation</a> that will help you to configure roles properly in production. 

If you have a complex organizational structure, consider creating <a href="https://doc.cuba-platform.com/manual-7.1/local_admins_example.html" target="_blank">local administrators</a> for each branch instead of several “super-admin” users at the organization level.

### Export Roles to Production

Before the first deploy, you usually need to copy roles and access groups from your development (or staging) server to the production one. In CUBA, you can do it using a built-in administrative UI instead of doing it manually. 

To export roles and privileges you can use ```Administration -> Roles``` screen. After the file is downloaded, you can upload it to the production version of the application. 

![text]({{strapiUrl}}/uploads/b5aa56988865408e93a56ab957e73550.png)

For Access Groups there is a similar process, but you need to use ```Administration -> Access Groups``` screen for this. 

![text]({{strapiUrl}}/uploads/a76dfb16cc17495cb9af79cf831d2988.png)

## Configuring Application 

The production environment is usually different from the development one, as well as application configuration. It means that you need to perform some additional checks to ensure that your application will be running smoothly when it comes to prod. 

**Configure Logging**

Ensure that you configured the logging subsystem properly for production: log level is set to the desired level (usually it is INFO) and logs won’t be erased at the application restart. You can refer to the <a href="https://doc.cuba-platform.com/manual-latest/logging.html" target="_blank">documentation</a> for the proper log set up and useful loggers reference.  

If you use Docker, use <a href="https://docs.docker.com/storage/volumes/" target="_blank">Docker volumes</a> to store log files outside the container. 

For the proper logging analytics, you can deploy a special facility to collect, store and analyze logs. Examples are <a href="https://www.elastic.co/what-is/elk-stack" target="_blank">ELK stack</a> and <a href="https://www.graylog.org/products/open-source" target="_blank">Graylog</a>. It is recommended to install logging software to a separate server to avoid a performance impact on the application.   

**Running in Clustered Configuration**
CUBA applications can be configured to run in a <a href="https://doc.cuba-platform.com/manual-latest/scaling.html" target="_blank">cluster configuration</a>. If you decide to use this, you need to pay attention to your application architecture, otherwise, you may get unexpected behavior from your application. We’d like to draw your attention to the most used features that you need to tune specifically for the cluster environment:

***Task scheduling***
If you want to execute a scheduled task (or tasks) in your application like daily report generation or weekly email sending, you can use the corresponding framework <a href="https://doc.cuba-platform.com/manual-latest/scheduled_tasks.html" target="_blank">built-in feature</a>. But imagine yourself as a customer that got three identical marketing emails. Are you happy? This may happen if your task is executed on three cluster nodes. To avoid this, prefer the <a href="https://doc.cuba-platform.com/manual-latest/scheduled_tasks_cuba.html" target="_blank">CUBA task scheduler</a> that allows you to create singleton tasks. 

***Distributed Cache***
<a href="https://doc.cuba-platform.com/manual-latest/entity_cache.html" target="_blank">Caching</a> is the thing that may improve application performance. And sometimes developers try to cache almost everything because memory is pretty cheap now. But when your application is deployed on several servers, the cache is distributed between servers and should be synchronized. Synchronization process happens over a relatively slow network connection and this may increase response time. The advice here - execute load tests and measure performance before making a decision about adding more caches, especially in a clustered environment. 

## Conclusion
CUBA Platform simplifies development, and you probably finish development and start thinking about going to production earlier than you expected. But deploy is not a simple task, whether you use CUBA or not. And if you start thinking about the deploy process on the early development stage and follow simple rules stated in this article, there is a good chance that your way to production will be smooth, requiring minimal efforts, and you will not face serious issues. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What is Rapid Application Development]]></title>
            <link>https://www.jmix.io/cuba-blog/what-is-rapid-application-development</link>
            <guid>https://www.jmix.io/cuba-blog/what-is-rapid-application-development</guid>
            <pubDate>Fri, 28 Feb 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/a6b0b9ec34c24fb3b51546ecf73e1525.svg">Rapid application development (RAD) model was formalized by James Martin in 1991 as an alternative to the rigid waterfall processes. The classic waterfall approach works perfectly in construction and many other industries where scope changes are rare and expensive. If you started building a bridge, it is unlikely that you would swap it for a ferry halfway through the process.]]></description>
            <content:encoded><![CDATA[Rapid application development (RAD) model was formalized by James Martin in 1991 as an alternative to the rigid waterfall processes. The classic waterfall approach works perfectly in construction and many other industries where scope changes are rare and expensive. If you started building a bridge, it is unlikely that you would swap it for a ferry halfway through the process.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA 7.2 - what's new?]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba72-whats-new</link>
            <guid>https://www.jmix.io/cuba-blog/cuba72-whats-new</guid>
            <pubDate>Tue, 18 Feb 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/b3551f5c017348e9a8c83aa23179ef07.jpg">The seventh version of the CUBA platform was a big step forward. Internal architecture improvements and the new IDE built a great basis for further improvements. And we continue adding new features to make a developer’s life easier and their work more productive.

]]></description>
            <content:encoded><![CDATA[The seventh version of the CUBA platform was a big step forward. Internal architecture improvements and the new IDE built a great basis for further improvements. And we continue adding new features to make a developer’s life easier and their work more productive.

In version 7.2 we’ve introduced a number of changes that might look like a major update, but thanks to the flexibility of version 7 it is just a natural platform evolvement.

## Polyglot CUBA

![text]({{strapiUrl}}/uploads/8e7b806b922a407ea7f9631832713a46.jpg)

Kotlin is now fully supported as a first-class language for CUBA-based applications. Now you can create entities, services, screen controllers and all other components using Kotlin. 

The code in Kotlin allows you to use shorter, more concise statements, so you can create applications even faster than before. Using IntelliJ IDEA’s language support in the IDE, we were able to implement the same functionality as for Java: context-driven injections, smart hints, code generation, etc. 

Here is an example of a simple entity. As you can see, the code is much shorter than for Java, there are no getters and setters, the code is perfectly readable and clear.
```
@NamePattern("%s|name")
@Table(name = "PETCLINIC_VET")
@Entity(name = "petclinic_Vet")
class Vet : StandardEntity() {
   @NotNull
   @Column(name = "NAME", nullable = false, unique = true)
   var name: String? = null

   companion object {
       private const val serialVersionUID = -8600988577624886948L
   }
}
```

Screen controllers will look pretty familiar for anyone who worked with CUBA before:
```
@UiController("petclinic_Vet.edit")
@UiDescriptor("vet-edit.xml")
@EditedEntityContainer("vetDc")
@LoadDataBeforeShow
class VetEdit : StandardEditor<Vet>() {
   @Inject
   private lateinit var vetService: VetService

   @Subscribe("assignVisit")
   private fun onAssignVisitClick(event: Button.ClickEvent) {
       vetService.scheduleVisit(editedEntity, LocalDateTime.now());
   }
}
```

And service:
```
interface VetService {
   companion object {
       const val NAME = "petclinic_VetService"
   }
   fun scheduleVisit(vet: Vet, visitDate: LocalDateTime): Visit
}


@Service(VetService.NAME)
class VetServiceBean : VetService {
   @Inject
   private lateinit var dataManager: DataManager

   override fun scheduleVisit(vet: Vet, visitDate: LocalDateTime): Visit {
       //Business logic for a visit scheduling
   }
}
```

The code is fully compatible with Java, you can even mix those Kotlin and Java in the same application. 

And finally, programming on Kotlin is fun (no pun intended)!

## Security Subsystem Update

![text]({{strapiUrl}}/uploads/7181df281d0f45c3a8b4071ba4b4da54.jpg)

Security is always important. We did a thorough review of our security subsystem and decided to use the “denied by default” approach. It might sound unusual for those who worked with CUBA before, but the motto “better safe than sorry” is incredibly relevant in the time of personal data leaks. As usual, we provide a migration path for applications developed with the previous CUBA versions. 

One more important thing - design-time role definitions. Now you can define access rules in Java code, therefore, you won’t need to export roles definitions from your test environment and import them to the production version. We do not abandon traditional runtime role definition, we just add one more feature to our security subsystem. It is up to you whether you want to use runtime roles, design-time ones or both. 

Here is the example that defines access rules for entities, attributes, and screens:

```
@Role(name = "Customers Full Access")
public class CustomersFullAccessRole extends AnnotatedRoleDefinition {

    @EntityAccess(target = Customer.class,
            allow = {EntityOp.CREATE, EntityOp.READ, EntityOp.UPDATE, EntityOp.DELETE})
    @Override
    public EntityPermissionsContainer entityPermissions() {
        return super.entityPermissions();
    }

    @EntityAttributeAccess(target = Customer.class, modify = {"name", "email"})
    @Override
    public EntityAttributePermissionsContainer entityAttributePermissions() {
        return super.entityAttributePermissions();
    }

    @ScreenAccess(allow = {"application-demo", "demo_Customer.browse", "demo_Customer.edit"})
    @Override
    public ScreenPermissionsContainer screenPermissions() {
        return super.screenPermissions();
    }
}
```
It might look more verbose than “traditional” runtime definition, but this approach allows us to set up a bit more fine-grained access to various application components. In combination with newly introduced scopes, the updated security subsystem will make your application safer.

## Better Generic User Interface

We continue to support and update the Generic UI subsystem. In this version, we made our default side menu collapsible to save more space on the application screen. You can see this as soon as you start your application.

As for the screen internals: now, developers can define views in XML screen descriptors, so there is no need to create views in the separate file. 
```
<data> 
    <instance id="orderDc" class="com.company.sales.entity.Order"> 
        <view extends="_local"> 
            <property name="lines" view="_minimal">
                <property name="product" view="_local"/>
                <property name="quantity"/>
            </property>
            <property name="customer" view="_minimal"/>
        </view>
        <loader/> 
    </instance>
</data>
```
In addition to that, we’ve added a number of smaller changes to simplify developer’s work:
- Flexible positions for elements in forms
- Initial sorting for grids
- Select/Deselect all command for grids
- Button shortcuts
- Date and time field improvements
- And more

## Simplified Deployment

![text]({{strapiUrl}}/uploads/426bec6385344b0abb16e028fae96abf.jpg)

In this version, you can configure database connections directly in the application. As an alternative to JNDI definitions, you can define connection properties in the ```app.properties``` file. 
```
cuba.dbmsType = hsql
cuba.dataSourceProvider = application
cuba.dataSource.username = sa
cuba.dataSource.password =
cuba.dataSource.dbName = petclinic
cuba.dataSource.host = localhost
cuba.dataSource.port = 9010
```
This feature makes the application independent of the application server environment. And this becomes more powerful combined with spring profiles - another feature of the version 7.2. 

Spring profiles allow you to define beans that will be specific for a deployment environment. For example, you can have different implementations for development and production servers. 

```
public interface HelloService {
    String NAME = "demo_helloService";

    String hello(String input);
}

@Service(HelloService.NAME)
@Profile("dev")
public class HelloDevServiceBean implements HelloService {
    @Override
    public String hello(String input) {
        return "Development stub: hello " + input;
    }
}

@Service(HelloService.NAME)
@Profile("prod")
public class HelloProdServiceBean implements HelloService {
    @Override
    public String hello(String input) {
        return "Production service: hello " + input;
    }
}
``` 
A profile can be activated either in ```web.xml``` file or by setting the environment property ```spring.profiles.active``` in the command line:

```
java -Dspring.profiles.active=prod -jar app.jar
```
Spring profiles can be applied not to beans only, but also to configuration files. For example, you can define profile-specific data source connection properties in ```<profile>-app.properties``` file. Or specify different SMTP servers for test and production environments. Say “no” to test emails in your customer’s inbox folders!

## CUBA Studio Update

All the features mentioned above are supported in CUBA Studio. Our main development tool is also under constant development. We’re adding new features, utilizing new IntelliJ APIs and improving code generation algorithms trying to automate all that can be automated, so you don’t have to write repetitive boring boilerplate code. 

![text]({{strapiUrl}}/uploads/a7e5d7456c874f16952b6fc1a75fbf8f.jpg)

The full list of updates can be found <a href="https://www.cuba-platform.com/discuss/t/studio-13-beta-published/11219" target="_blank">here</a>, let’s review only the most important ones:
- New login screen template. Now you can use a more “branding-friendly” login window.
- Screen designer UI was reworked, we split its panels to save IDE window space and allow developers to see changes while they edit XML layout.
- Project Wizard was extended to support new programming languages and allow us to enter additional information like locale and main datastore properties.

## Conclusion

With this update, development with the CUBA framework becomes easier,  faster and more exciting. With Kotlin, you have a chance to use one of the top emerging programming languages. 

Deployment to different environments is simplified thanks to spring profiles and data sources configured in the application.  

Improvements in the generic UI will help you to bring a designer’s fantasies about the ideal user interface to reality with greater accuracy. 

And we still keep the framework backward compatible, so your application upgrade to version 7.2 should be as smooth as possible.

You can find the release notes with all changes <a href="https://files.cuba-platform.com/cuba/release-notes/7.2/" target="_blank">here</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Vaadin 10+ as the Future of CUBA UI]]></title>
            <link>https://www.jmix.io/cuba-blog/vaadin-10-evaluation</link>
            <guid>https://www.jmix.io/cuba-blog/vaadin-10-evaluation</guid>
            <pubDate>Mon, 13 Jan 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/cfb95f3c96a44c2ca0cf26ffa3a95b15.png">Since the very beginning, Vaadin was a cornerstone and crucial part of CUBA Platform UI. The article describes evaluation of the completely new Vaadin framework.]]></description>
            <content:encoded><![CDATA[Since the very beginning, Vaadin was a cornerstone and a crucial part of the CUBA Platform UI. Thanks to its innovative approach, it helped CUBA to bring enterprise UI development to a very promising (and default nowadays) WEB land. One of the most exciting parts of Vaadin is that the whole development is *isomorphic* and being done primarily using Java, rescuing the developers from interacting with a fairly unstable and quickly changing front-end world.

![Vaadin 8 project structure]({{strapiUrl}}/uploads/ef7dfab71c784d03ab69673559a15fe0.png)

As you may see, one of the important parts of Vaadin is a feature-rich UI (based on GWT widgets in case of Vaadin 8). 

Compared with modern web UI kits even nowadays Vaadin widgets still belong to the most sophisticated and advanced ones, especially in terms of enterprise requirements. Primarily, we are talking about such heavily used in typical CUBA applications components as Tables, Grids, ComboBoxes. For example, just try to find a popular UI kit with a Table which provides drag-n-drop column reordering or dynamic column control.

## Our Story with Vaadin

CUBA Platform has a long story of using Vaadin. The platform provides to its users almost seamless migration from Vaadin 5 to Vaadin 8. To provide such kind of migration we had to build and keep our API on top of Vaadin. Also, we extend some components and even <a href="https://github.com/cuba-platform/vaadin" target="_blank">fork</a> the framework itself to provide unique functionality for our customers and inject required extension points. On the server-side the platform provides data binding and data-aware components which are the most important features of the Generic UI.

To speed up the development and to enable using rapid development tools (Studio) we introduced XML descriptors - declarative approach to build data-bound UI:
```xml
    <layout>
        <grid spacing="true" height="200">
            <columns count="4"/>
            <rows>
                <row flex="1">
                    <label value="Field 1" align="MIDDLE_LEFT"/>
                    <textField height="100%"/>
                    <label value="Field 2" align="MIDDLE_LEFT"/>
                    <textField height="100%"/>
                </row>
                <row flex="2">
                    <label value="Field 3" align="MIDDLE_LEFT"/>
                    <textField height="100%"/>
                </row>
            </rows>
        </grid>
    </layout>
```

`Pure Vaadin:`
```java
    GridLayout tableHeader = new GridLayout(3, 2);
    
    Label nameLabel = new Label("Field 1");
    nameLabel.setWidth(lastnameWidth + 2 * 6, Unit.PIXELS);
    tableHeader.addComponent(nameLabel, 0, 0, 0, 1);
    Label countryLabel = new Label("Field 2");
    countryLabel.setWidth(countryWidth + 2 * 6, Unit.PIXELS);
    tableHeader.addComponent(new Label("Field 3"), 1, 0);
    Label bornLabel = new Label("Field 4");
    bornLabel.setWidth(bornWidth + 2 * 6, Unit.PIXELS);
    tableHeader.addComponent(bornLabel, 2, 0, 2, 1);
    tableHeader.addComponent(countryFilterBox, 1, 1);
    
    // Put the header and table inside a vertical layout
    layout.addComponent(tableHeader);
    layout.addComponent(table);
    
    // Adjust the table height a bit
    table.setPageLength(table.size());
```

We managed to build a list of our own components (based on Vaadin primitives):

- GroupTable
- Form (formerly FieldGroup)
- PickerField
- LookupPickerField
- TokenList
- MaskedField
- SuggestionField
- CurrencyField

That being said, CUBA provides quite a lot on top of the Vaadin Framework to make the developers' life easier and bring the development to a higher level. CUBA team did a heavy-lifting to enable very smooth, literally invisible migration when updating the underlying Vaadin Framework.


## New Challenges

### Customization and Native Interaction

GWT is quite complex, and creating UI widgets is a challenging and time-consuming process. Experienced developers know for sure that there is a high price you have to pay when you work with artificial abstractions over the native platform. In the case of GWT, we have to interact with browser JS APIs from the Java world. 

### Responsive Layouts
The ability to be adjustable for different screen sizes has become a crucial requirement even for enterprise interfaces. Making responsive UI is hard just because of the aforementioned additional abstractness over the native platform. Though you can use CssLayout or special <a href="https://www.jmix.io/cuba-platform/marketplace/sw-responsive/" target="_blank">add-on</a> to create responsive UI, standard layouts and calculations on the server side do not play well for such purposes.

### Using Third-Party Libraries
Web evolves very fast, there is an enormous amount of web packages (npm >1M) which are mostly useless in Vaadin 8 apps as it does not use modern front-end tooling and build systems.

### GWT Development is Stuck
At some point, Google stopped active development of GWT. It’s not only about official support but more about the ecosystem.

## Vaadin Flow
To be more open to the front-end ecosystem, Vaadin started to develop the successor of the Vaadin Framework. The core of the new approach is <a href="https://github.com/vaadin/flow" target="_blank">Vaadin Flow</a> - technology that provides a server-side model and basic data binding for a new UI layer based on Web Components instead of GWT widgets.

Consider the following diagram:

![Vaadin 10 based project]({{strapiUrl}}/uploads/7b0c6437c1f0420683864e941b1dfe61.png)

As you may see, Vaadin has replaced its GWT-based client-side with the new one based on native web technologies.

### Vaadin Components
New Vaadin <a href="https://github.com/vaadin/vaadin" target="_blank">components</a> are successors of Vaadin GWT widgets. They are Web Components built from scratch using pure web technologies (HTML, JavaScript) and Polymer 2 library.

### Web Components
Initially, Web Components were a set of standards implemented in most modern browsers:
 
- Custom Elements
- Shadow Dom
- HTML Templates
- HTML Imports -> ES Modules

For a long time, Web Components were very promising, and many people (including me) considered them as a native replacement for frameworks like React and Angular which also utilize component-based approach. But with time it became obvious that some of these standards were dropped by browsers, and some require serious improvements. Nowadays, from the list above only Custom Elements and Shadow DOM are still used in web application development. HTML Imports was dropped even from Chrome. HTML Templates nowadays look already outdated and, for example, new Polymer approach: <a href="https://github.com/Polymer/lit-html" target="_blank">lit-html</a> use them only behind the scenes.

We also had an experience with Web Components as part of our attempt to build a client-side centric UI on top of Polymer library. At some point, we decided to shift our efforts to the React-based approach since Polymer, despite its brave mission of Web Component enablement solution, had poor developer experience, small ecosystem (even after several years of existence), and finally made an unclear release of Polymer 3 which at the moment of releasing was `not recommended` for a new projects solution. Polymer users had to wait for almost a year until lit-html and LitElement were finally released.

Another observation coming from our experience: despite being heavily promoted by advocates of `use the Platform` motto, it’s still barely possible to escape transpilation/bundling step when developing modern front-end applications. While standards were making a hard way to be adopted by all browsers and settle APIs, the community created a lot of tools and libs to solve the same problems.

For example, the main purpose of Shadow DOM is to encapsulate CSS styles from being spilled to/from local DOM of the component. The idea is great, but it took several years to be adopted by most browsers (thankfully Edge moved to Chromium). At the same time, the React ecosystem was fulfilled by a <a href="https://github.com/MicheleBertoli/css-in-js#features" target="_blank">huge amount</a> of styling libraries that solve the same task and even more without <a href="https://twitter.com/WebReflection/status/1205603854886289409" target="_blank">significant</a> <a href="https://dev.to/webpadawan/beyond-the-polyfills-how-web-components-affect-us-today-3j0a" target="_blank">pitfalls</a> of Shadow DOM.

Nevertheless, Web Components have a very important distinctive feature: they are part of the Platform (browsers). Being not tied with any particular framework, in theory, they are universal and can be used everywhere. From that perspective, it looks like a reasonable choice for UI Kits or standalone components (but not for applications), made not only by Vaadin but, for example, also by <a href="https://ionicframework.com/blog/introducing-ionic-4-ionic-for-everyone/" target="_blank">Ionic</a> and <a href="https://github.com/SAP/ui5-webcomponents" target="_blank">SAP</a>.

## Vaadin 14

Vaadin 10 based on Vaadin Flow has been <a href="https://vaadin.com/blog/vaadin-10-is-out-" target="_blank">released</a> in the middle of 2018. It quickly became obvious that the UI kit misses a lot of important components and contains only basic ones. Moreover, the client-side build pipeline included a bower dependency manager - a tool that was already deprecated in 2017 and does not intersect with the de-facto standard npm ecosystem. 

So we considered Vaadin 10 release as experimental and decided to wait until the new technology becomes more stable. There were 3 major releases until Vaadin 14 LTS <a href="https://vaadin.com/blog/top-14-new-features-in-vaadin-14" target="_blank">arrived</a> in August of 2019 with highly demanded npm support and more robust UI kit. That urges us to take a closer look and make some hands-on experience with Vaadin 14.

### UI Kit
Even without deep dive into the codebase, it was clear that many properties and behaviors changed in comparison to Vaadin 8 widgets. Generally, it’s not bad but for CUBA it means that in some aspects there will be no direct replacements of the currently supported features/APIs.

In terms of completeness there are still some missing core components that are already used in CUBA:

- Calendar
- Tree
- TwinColumn

Some of the previously free components and features become part of Pro Components: for example, RichTextArea now is part of Pro components, edit mode of Grid is available in Vaadin Grid Pro.

### PickerField
As part of our evaluation process we reimplemented CUBA’s PickerField component for Vaadin 14:

![text]({{strapiUrl}}/uploads/2d9ea421d88342359cc48be5db3e65ce.png)

Speaking of the server-side, Vaadin Flow provides amazing capabilities to interact with the client-side (DOM elements, events, etc) using Java APIs. Vaadin components are shipped with a convenient Java API:

```
    Accordion accordion = new Accordion();
    ...
    accordion.open(1);
```

Non-Vaadin components have no such APIs, but you can still use generic methods over DOM API for any element:

Example 1
```
    if (value == null) {
        getElement().removeProperty("value");
    } else {
        getElement().setProperty("value", getStringRepresentation(value));
    }
```

Example 2
```
    getElement().appendChild(new Element[]{Element.createText(text)});
```

While the server-side was pretty slick and clear, the client-side took almost 90% of our efforts. The first notable thing we should mention is that core Vaadin components are currently built with Polymer 2. To support Polymer 3 for Vaadin 14+ they are seemingly auto-converted. Generally, Polymer 2 and Polymer 3 have the same API (that’s why auto-conversion is possible), however, there are subtle differences in imports and styles declarations.

Another <a href="https://github.com/material-components/material-components-web-components/issues/526" target="_blank">hard topic</a> is styling and customization: thanks to Shadow DOM you simply cannot apply styling to random elements (only to those which are designed to be styleable by using custom CSS properties). Vaadin components have slots (another powerful, yet intricate part of Shadow DOM) for customization. They are great for simple use cases but you quickly face limitations when trying to implement more advanced use-cases.

So when implementing PickerField we end up by copy-pasting styles and other parts of Vaadin components and build the component on top of the native `input` element (the only reusable things imported from @vaadin were a couple of Mixins).

We don’t blame Vaadin as it has not been designed (and not ought to be) as a foundation for another UI kit, it just indicates that for us it will be a huge amount of work on the client-side to support all additions we provide for a long time for our developers. The Work which currently should be based on Polymer 3 (already in maintenance mode) with all known developer experience flaws of Polymer2.

## Latest news

Just at the time of writing this article, Vaadin announced that all core components will be rewritten on TypeScript and LitElement. We look positively at this decision since our vast experience with TypeScript confirms that it helps to avoid lots of bugs caused by the absence of static typing in JS, helps to understand the structure of codebase, to perform safe refactorings, etc.

LitElement/lit-html looks a little more doubtful though: we understand the choice because it’s a successor of Polymer, and utilizes powerful declarative rendering ( view=f(state) ) approach invented by React. But it’s still:

- Very <a href="https://github.com/Polymer/lit-html/releases" target="_blank">new</a>.
- Has a runtime (unlike compiled approaches like <a href="https://stenciljs.com/docs/faq#what-dependencies-does-the-stencil-runtime-have-" target="_blank">Stencil</a> and <a href="https://svelte.dev/" target="_blank">Svetle</a>). To support both Polymer and Lit- based components Vaadin should ship both libraries to the client-side.
- Poor IDE support. There are a few of VS Code plugins, but <a href="https://youtrack.jetbrains.com/issue/WEB-32640" target="_blank">no support</a> in IntelliJ/WebStorm, which makes lit-templates look really messy.
- Not SSR - friendly.

Many new questions arise:
Will LitElement + TypeScript supersede current Polymer 3 based approach to develop application front-end?
If yes - how such React-like rendering will work altogether with server-side Java API?

### Update
Vaadin 15 is coming with client-side bootstrapping and TypeScript <a href="https://vaadin.com/blog/vaadin-simplicity-now-also-in-typescript" target="_blank">support</a>.

## Conclusion
Vaadin is a unique product that enables convenient web development for Java. Vaadin Flow brought a completely new client-side approach which we think is quite promising. However, the component set is still evolving and on its way to stability. 

One thing we can say for sure: as a consequence of the completely new client-side we'll be unable to provide a smooth migration path to the new UI built on top of Vaadin Flow.

Also, we feel it’s still a little bit fuzzy and unstable in terms of client-side technologies to start a massive migration of all CUBA components on top of it. We decided to postpone the active development until the new set of web components becomes available. We still keep an eye on the Vaadin development and ready to re-evaluate it as soon as it becomes more stable.

At the same time, we are also trying to provide an alternative, client-side friendly approach to create UI: see our recent <a href="https://www.cuba-platform.com/blog/cuba-platform-typescript-sdk-and-rest-api/" target="_blank">blogpost</a> on TypeScript SDK and React Client.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Low Code Platforms - a Dangerous Bet]]></title>
            <link>https://www.jmix.io/cuba-blog/low-code-platforms-a-dangerous-bet</link>
            <guid>https://www.jmix.io/cuba-blog/low-code-platforms-a-dangerous-bet</guid>
            <pubDate>Mon, 23 Dec 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/1062d7041ad4449bac92ed07de858f82.png">The low code application platforms (LCAP) have emerged in response to the complexity and variety of the modern software development landscape. Mendix is one of the most prominent players in this space according to Gartner, so let me use it as a reference in this article. However, similar conclusions would apply to Outsystems, Appian, Kony, Betty Blocks and many other platforms.]]></description>
            <content:encoded><![CDATA[The low code application platforms (LCAP) have emerged in response to the complexity and variety of the modern software development landscape. <a href="https://www.mendix.com/" target="_blank">Mendix</a> is one of the most prominent players in this space according to Gartner, so let me use it as a reference in this article. However, similar conclusions would apply to Outsystems, Appian, Kony, Betty Blocks and many other platforms.

![text]({{strapiUrl}}/uploads/5b22761059974d2195051b11ed1e1fdc.png)

Being sold to business executives, LCAPs originally claimed that business users (aka *citizen developers*) can create enterprise-grade solutions. So, are the developers now obsolete? Well, a few years later Mendix confesses:

![text]({{strapiUrl}}/uploads/a057cb6ba0bb4b8e9c896d9907e0e2f6.png)

What a twist! I guess the guys at Mendix realized that anything more complex than a basic CRUD system still requires a professional software engineer, just like servicing your car beyond pumping tyres usually requires a professional mechanic.

Unfortunately, current low code platforms are just not made for a developer. Moreover, relying on them in the long term can be a dangerous bet for the business. Below I will explain why. 

## Great for prototyping

Mendix is indeed a great option for citizen developers to automate simple business operations, or deliver working prototypes. In a visual designer you can define data model, scaffold responsive UI using a collection of widgets and templates, and even describe logic with microflows:

![text]({{strapiUrl}}/uploads/61818da1fecb4adba91eab5838c46690.jpg)

When you’re done, you can deploy your app to the Mendix cloud with one click and see it working. Looks simple and works like a charm, so this is often just enough to get a business executive sign a cheque.

However, as your app passes the prototype stage, both user interaction and business logic almost inevitably become more complicated. Here comes the stage, when you require a professional to push the project forward to avoid ending up in a mess.

So, let’s look at this from the developer’s standpoint.

## (S)low code

Any logic - whether calculations or user interaction - must be described in a microflow, a visual representation of the code as shown above. There are a few issues here.

First of all, this is just *slow*. Imagine dragging, configuring and connecting tens of stencils versus writing 10 lines of code in a good IDE. Over certain size, your microflow inevitably becomes unmanageable.

Second is *readability*. Those stencils look nice, but what’s behind that *Sub_RegistrationValidation*? You cannot really read it without having to dive in.

As a getaway, Mendix offers *Java actions*. This means that you can invoke Java methods (with serious limitations for cloud deployment) from a microflow. You can write Java code in Eclipse, which is OK, though many would prefer IntelliJ - the leading IDE. The downside is lack of *transparency*: all entry points to your code are in microflows, so debugging or tracing the dependencies is complicated. The logic flow is scattered between the two worlds.

The last bit I have to mention is version control. Good news is that there is one. Bad news is that it is a restricted subset of Subversion. Say bye to git flow.

## No Control

Anyone familiar with the Java ecosystem, cannot underestimate the power of open source. When you have an exception somewhere down the stack, you see the code where it happened. You can debug it to figure out exactly what’s going on. You can google a solution. You can submit a pull request. Worst case, you can fork. You are in control. 

Forget about that with Mendix. The framework is proprietary so the underlying stack is a black box. All you’re left with is paid support or praying someone will help on the community <a href="https://developers.mendix.com/" target="_blank">forum</a> with ~200 questions a month (compare that to Spring tag on <a href="https://stackoverflow.com/questions/tagged/spring" target="_blank">stackoverflow</a>!).
 
## Vendor lock

Mendix probably gets poked for that quite often. They even put an <a href="https://www.mendix.com/evaluation-guide/enterprise-capabilities/no-vendor-lockin" target="_blank">article</a> to explain how you are not locked into them. If you can read behind the lines though, it says:

*You can get your data, DDL, UI resources and code (microflows magically converted to Java).*

Will this run or compile without Mendix runtime and API? A rhetoric question. In fact, this would require a full system re-write. You are locked into a proprietary platform. You do not own the system you’ve built.

## Limited Scalability

Mendix marketing is targeted at the largest companies out there, so “scalability” term pervades their marketing materials. In 2017 they introduced “stateless runtime” - which means that all session information is either stored on the client or persisted. In theory, this means unlimited horizontal scalability. Sounds cool, but there is a catch - the database. 

Database is the usual bottleneck of an enterprise application. So, what stores the data behind the horde of stateless Mendix servers? No surprise - it is the good old relational database. In the case of Mendix cloud it is PostgreSQL. There is no caching and the DDL generated by Mendix is questionable. For example, I’ve encountered an interim table typically used to model N:M relations generated for a 1:N relation.  

This would be fine if you had control. Oracle and others have proven that RDBMS can work at scale. You could optimize DB structure, cache data or even use solutions like Citus for true scalability. But you don’t. 

The only DB scaling option is scaling through read-only replicas (e.g. Amazon RDS), but this does not help with writes. 

To conclude, there is a fundamental scalability limitation and a lack of options for fine-tuning performance.

## (De)skilled Staff

Deskilling sounds like a charm for any manager. No need for expensive, hard-to-find professionals. In reality, this plays a bad trick. When you actually need a developer for your project, you’ll be struggling to find a good one. For a professional developer, this means career dead-end.  

## Prices that Bite

Last but not least. A <a href="https://www.mendix.com/pricing/" target="_blank">single app license</a> starts from $1875 a month, limited to 50 internal users with a 3-year commitment. Enterprise license with the ability to deploy on premises starts from $7825, or almost $100K p.a. A decent enterprise with several thousand users will likely be paying multi-million annual fees.

Remember we are talking about relatively simple applications, as you could see from the above. To me, this is crazy. This pricing model is also prohibitive for distributing the applications you built.

## Why are LCAP still popular then?

In my view, the answer is *frustration*. Managing development teams in large organizations - whether external or internal - turns out to be overly complicated. Advance budget planning, multiple stakeholders like architects or line managers with own agenda, lack of responsibility...  It is just too hard to push your idea to implementation. The funniest thing is that a typical knee jerk reaction is hiring more developers and, of course, managers. Needless to say, this makes things even worse. I know a couple of banks with over 10 000 (!!!) developers and I know for a fact that at least half of them are doing useless work. In despair, business executives turn to magical solve-all-your-problems solutions like LCAP. 

Getting out of this mess is a subject for a separate article. But this is a management issue, not a technological one. Skipping through details, if you manage to get a team of 3-10 reasonably qualified people fully dedicated to a project and with direct contact with the stakeholders and a decision-maker, you’ll get great results faster and cheaper than you think.

## What are the Alternatives?

There is a great choice of developer tools and frameworks these days. As an example, Spring Framework is the most popular open-source technology for enterprise software, which can be nicely coupled with web frameworks like React or Angular. Tools like <a href="https://start.spring.io/" target="_blank">Spring Initializr</a> and <a href="https://www.jhipster.tech/" target="_blank">JHipster</a> made this much easier over the last few years.

If you need faster results and easier adoption, it is worth looking at RAD tools like <a href="https://www.cuba-platform.com/" target="_blank">CUBA Platform</a>. It is built on top of the same Spring Framework, complementing it with visual development tools and a marketplace of seamlessly integrated add-ons. This would probably be the closest alternative for LCAP for developers, still offering flexibility and convenient development process.

So there are many options around and the final choice should depend on the task, as well as your team skills and preferences. 

## Wrapping up

Low code platforms are great for prototyping. They bridge business stakeholders with IT enabling them to produce visible results and gain common vision times faster. As there are very few users, the costs are also low. **And this is exactly where you should seriously consider stopping!**

If you continue, the development speed will slow down and you will be hooked more and more into an expensive and limiting proprietary platform.

As long as AI has not taken our jobs, enterprise software should be built by professional developers. So set an achievable goal, knock up a good small team with a competent lead, let them pick their tools and don’t forget to submerge them into the business domain. Very soon, you will see your ideas taking shape!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Platform: TypeScript SDK and REST API]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-typescript-sdk-and-rest-api</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-typescript-sdk-and-rest-api</guid>
            <pubDate>Wed, 18 Dec 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/62621bfd6a584f2cb90de33f3ba88341.jpg">In this article, we will talk about the feature of the CUBA platform that exists for quite a long time, but is still not widely known - front-end SDK generator, and see how it works with CUBA’s REST API addon.
]]></description>
            <content:encoded><![CDATA[In this article, we will talk about the feature of the CUBA platform that exists for quite a long time, but is still not widely known - <a href="https://github.com/cuba-platform/frontend" target="_blank">front-end SDK generator</a>, and see how it works with CUBA’s <a href="https://github.com/cuba-platform/restapi" target="_blank">REST API addon</a>. 


## Java+JavaScript - marriage born in web

Only eight years ago we, Java developers, used JavaScript as a "second-class citizen" language in our web applications. Back in those days its purpose was adding some dynamics to the web pages generated on the server-side with frameworks like JSF, Struts, Tapestry or Thymeleaf. Nowadays we are witnessing an emerge of JavaScript as the language number one for the client-side development with such frameworks as React, Vue or Angular, and with Node.js it even comes to the server-side. 

In reality, we develop web applications that may use different languages on different tiers: JavaScript for the client-side UI, Java for the business logic processing, SQL to fetch data from the database, Python for data analysis, etc. And we have to combine all those languages into one application using various technologies. The most common example - REST API. Based on platform-agnostic HTTP protocol and simple JSON format, it is now the default method to stitch the client-side JS and the server-side Java.

But even the best stitch cannot be seamless. There is always a problem with API definition: which methods to call, what the data model is and whether we should pass a street address as a structured object or just as a string.

How can we help our JavaScript fellows to create their code faster and avoid miscommunication? 

## Is Swagger the ultimate answer? 

"<a href="https://swagger.io/" target="_blank">Swagger</a>" you say and right you are. Swagger is de-facto an industrial standard for designing, building, documenting and consuming REST API. There is a number of code generators that help with client SDK generation for different languages. 

CUBA Framework supports Swagger, every application with REST API add-on has the endpoint that allows downloading Swagger documentation in .json or .yaml format. You can use these files to generate a JS client.

Please consider the fact that Swagger is only an API documentation tool. But what kind of info a front-end developer wants to see in the API? The “classic” approach is:  map business functions to services and build a well-defined API. Then expose it as a set of REST services, add Swagger documentation and enjoy.  

Then why does GraphQL hit the trends making a buzz among front-end developers? And note that GraphQL share in web APIs world is growing. What is going on? It turned out that sometimes it is easier to give front-end developers a bit more “generic” API to avoid creating a lot of small APIs for use cases that might change frequently. E.g. for your shopping basket in the web UI, you need an order with prices only first, then an order with totals, etc. GraphQL is also a great tool to avoid both overfetching and underfetching as well as querying several APIs at once to get a complex data structure. 

OK, it looks like the application should expose not only services but also some generic APIs. This approach allows front-end developers to invoke complex business functions and gives them some degree of flexibility, so they won’t request API changes if they need just a different data representation for the UI. 

And there is one more problem that neither Swagger nor GraphQL or OData solves - what to do with the generated client code if something is changed. Direct one-time code generation is simple, but support is a different thing. How can we be sure that our front-end application will not fail after we remove an entity’s property?  

So, to speed up front-end development and simplify collaboration between back-end team and front-end team we need to:

1. Expose both business-specific and generic API
2. Generate front-end code based on the back-end data model and method signatures
3. Modify generated code with minimum efforts and potential bugs

We face all these challenges in CUBA with REST API add-on and front-end SDK generator.

## CUBA TypeScript SDK 

In CUBA, REST API add-on provides the following functionality:
- CRUD operations over the data model
- Execution of predefined JPQL queries
- Execution of services methods
- Getting metadata (entities, views, enumerations, datatypes)
- Getting current user permissions (access to entities, attributes, specific permissions)
- Getting current user information (name, language, time zone, etc.)
- Working with files

So we have everything we need to work with the application from any front-end client. All those APIs are described in <a href="https://doc.cuba-platform.com/restapi-7.1/#rest_swagger" target="_blank">swagger YAML or JSON file</a>, so you can start implementing the application right away.  

It is very important to set up security rules for the REST API users to prevent accidental endpoint exposure to all users. First, deny general REST API access for all users and then create special permissions for roles that need to access the desired functionality.    

But CUBA offers more than just REST API. You can <a href="https://github.com/cuba-platform/frontend#typescript-sdk" target="_blank">generate an SDK</a> that can be used as a basis for any front-end development framework: React, Angular, Vue or other. 

With the generator, you create a set of TypeScript classes that allows you to invoke CUBA API from your client application. 

To generate the SDK, you just need to run 

```
npm install -g @cuba-platform/front-generator
```
And then 
```
gen-cuba-front sdk:all
```
and all classes will be created for you. You can even generate a simple UI based on ReactJS, so your customers will be able to start working instantly with the CUBA-based application. The UI is pretty basic, but with CUBA you will get all the features instantly, including authentication, role-based access to data, entity graph retrieval, etc. 

Let’s have a closer look at what the SDK has.

### Data Model

The application data model is represented as the set of TypeScript classes. If we have a look a the <a href="https://github.com/cuba-platform/sample-session-planner" target="_blank">Session Planner</a> application used in the <a href="https://www.jmix.io/cuba-platform/learn/quickstart/studio/" target="_blank">QuickStart</a>, there is an entity there:

```
@NamePattern("%s %s|firstName,lastName")
@Table(name = "SESSIONPLANNER_SPEAKER")
@Entity(name = "sessionplanner_Speaker")
public class Speaker extends StandardEntity {
   @NotNull
   @Column(name = "FIRST_NAME", nullable = false)
   protected String firstName;

   @Column(name = "LAST_NAME")
   protected String lastName;

   @Email
   @NotNull
   @Column(name = "EMAIL", nullable = false, unique = true)
   protected String email;
//Setters and getters here
}
```

And in the SDK we’ll get a class:

```
export class Speaker extends StandardEntity {
   static NAME = "sessionplanner_Speaker";
   firstName?: string | null;
   lastName?: string | null;
   email?: string | null;
}
```
All associations and compositions will be preserved, therefore you will be able to fetch an entity graph instead of fetching entities one-by-one using several API calls. 

No more DTOs - you’ll get exactly the same data as described on the back-end.  

### Business Services

All the services exposed via REST in CUBA will have a TypeScript representation in the SDK. For example, if we expose the <a href="https://github.com/cuba-platform/sample-session-planner/blob/master/modules/core/src/com/company/sessionplanner/service/SessionServiceBean.java" target="_blank">Session Service</a> using REST API, you’ll get a TypeScript code that looks like this:

```
export var restServices = {
   sessionplanner_SessionService: {
       rescheduleSession: (cubaApp: CubaApp, fetchOpts?: FetchOptions) => (params: sessionplanner_SessionService_rescheduleSession_params) => {
           return cubaApp.invokeService("sessionplanner_SessionService", "rescheduleSession", params, fetchOpts);
       }
   }
};
``` 
Therefore you will be able to call it from the UI just by writing the following line:

```
restServices.sessionplanner_SessionService.rescheduleSession(cubaREST)({session, newStartDate}).then( (result) => {
   //Result handling
});
```
Handy, isn’t it? All the routine work is done for you.

### Generic API

If you  need to implement custom logic for front-end only, you can always use a set of functions defined in the core CUBA platform REST library such as:

```
loadEntities<T>(entityName: string, options?: EntitiesLoadOptions, fetchOptions?: FetchOptions): Promise<Array<SerializedEntity<T>>>;
deleteEntity(entityName: string, id: any, fetchOptions?: FetchOptions): Promise<void>;
```
Those functions give you a fine-grained access to CRUD operations with entities in the application. Security still stays, CUBA verifies all non-anonymous calls on the server-side and prevents fetching entities or attributes that do not comply with a user’s role. 

```
cubaREST.loadEntities<Speaker>(Speaker.NAME).then( (result => {
 //Result handling
}));
```

Using this generic API, a developer can create a JS application with the custom API layer created over the generic CRUD and deploy it to the node.js server implementing “<a href="https://samnewman.io/patterns/architectural/bff/" target="_blank">backend for frontend</a>” architectural pattern. Moreover, there may be more than one API layer implemented with this approach, we can implement a different set of APIs for different clients: ReactJS, Native iOS, etc. In fact, the generated SDK is the ideal tool for this use case.

What is not great with the generic API is the risk of underfetching or overfetching data when you either fetch more attributes than you need to or you don’t have enough attributes in the API descriptors. CUBA’s <a href="https://doc.cuba-platform.com/manual-latest/views.html" target="_blank">Entity Views</a> solve this problem on the back-end and we provide the same option for front-end developers! For each generated TypeScript class we create types that reflect views:

```
export type SpeakerViewName = "_minimal" | "_local" | "_base";

export type SpeakerView<V extends SpeakerViewName> = 
V extends "_minimal" ? Pick<Speaker, "id" | "firstName" | "lastName"> : 
V extends "_local" ? Pick<Speaker, "id" | "firstName" | "lastName" | "email"> : 
V extends "_base" ? Pick<Speaker, "id" | "firstName" | "lastName" | "email"> : 
never;
```
So, you can fetch an entity from the backend and you will get only specified attributes. Therefore, you don’t need to guess which attributes were fetched. And IDE will help you with code autocomplete. 

![text]({{strapiUrl}}/uploads/63f9cdf440a34cdb91ac1951d2b6ddba.jpg)

### API Updates

As it was mentioned, code generation is not even half of the development work. Changing and supporting the code is where most of the efforts are. CUBA’s TypeScript SDK generator analyses the code during the subsequent runs, tracks changes and updates it incrementally. And TypeScript compiler will ensure that you won’t forget to update your custom code that uses the SDK if you use TypeScript as the main development language on the front-end. 

## Conclusion

If you want to develop a JS-based client UI (React/React Native or Angular or Vue) for CUBA application in addition to generic UI you can use REST API add-on and TypeScript SDK. Whichever technology you decide to use, you can focus on design or performance to give the best user experience instead of doing routine coding tasks. And you can be sure that JS to Java communication as well as the support of changing APIs will be the smallest of your problems. 

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[RAD Platforms: 20 Years of Evolution ]]></title>
            <link>https://www.jmix.io/cuba-blog/rad-platforms-20-years-of-evolution</link>
            <guid>https://www.jmix.io/cuba-blog/rad-platforms-20-years-of-evolution</guid>
            <pubDate>Tue, 10 Dec 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/b33c71859a884ef389ff00f7baee2354.jpg">The RAD term may sound like an echo from the beginning of 2000s - have they been evolving? Let’s see.]]></description>
            <content:encoded><![CDATA[The modern software development landscape has dramatically changed over the past few years. To me it looks much like the accelerating expansion of our Universe. At the beginning of the second millennium the industry didn't look very fast but progressively moving. Nowadays the complexity and variety of technology grow over the speed of sound, faster and faster, bringing new programming languages, development tools, methodologies…

Technology becomes more comprehensive and complex for an obvious reason - to meet growing requirements for building global solutions like Uber, Facebook, Google and so on. Outstanding complexity is the price to be paid for the ability to build global monstrous systems. But should we pay the same price for creating relatively typical applications for business automation?

## Subject for Automation: Line of Business Applications 

The beginning of the 2000s was the time of extensive business automation under the motto: "if something could be automated it should be automated". The result of such automation is called Line of Business (LOB) Applications. It is quite a general term that describes a set of very important (mostly custom) applications developed with the only ultimate reason - to run business more efficiently. 

In general, LOB applications have the following distinctive features:

- Domain-specific - targeted on professionals in a certain domain area and not mass market
- Data-centric - hugely rely on relational databases, which plays a crucial role in the application
- Transaction-oriented (OLTP) - represent CA class of systems (highly consistent and available) assuming ACID compliance with each transaction
- Extensive Business Logic - contain a massive block of custom business rules and data processing algorithms
- Rich User Interface - introduce hundreds of functional interactive screens with relatively standard widgets (text fields, checkboxes, buttons, tables...)  

Functionality-wise LOB applications also share a common list of requirements:

- Authentication and support for industry standards like SAML and LDAP
- Role-based access control
- Row-level security
- Data changelog (aka data audit) 
- Interoperability, an ability to consume 3rd party APIs and provide an API for integrations
- Business process management engine and support for BPMN as an industry standard
- Reporting and business intelligence capabilities
- Integrations with frequently used services like emailing (SMTP and IMAP), file storage (Amazon S3, WebDAV), search engines and so on…
- Scalability, so a solution can grow along with business growth

High demand in LOB applications formed a market of so-called <a href="https://www.cuba-platform.com/rapid-application-development/" target="_blank">Rapid Application Development</a> tools, which were ultimately focused on making the development of LOBs way more efficient. 

## The Evolution of RAD Platforms

In mid 90s demand for business automation started to grow exponentially. Hence, many RAD platforms emerged in response, providing a fast track for the development of LOB applications. RADs combined easy-to-learn programming languages with productive development tools, so virtually anyone could create a basic LOB application in record time! Microsoft Access, Oracle Forms, FoxPro and of course Borland Delphi (a trendsetter of those days) supported automation boom. So, by the end of the first decade of the 2000s, a huge number of LOB systems have been developed on RAD platforms.

What RADs had missed back then was oncoming web era. The web user interface turned out to be an essential requirement accompanied by adjacent requests for scalability, availability and others. These factors had ruined the popularity of Delphi and other RAD tools as they were not able neither to fulfill the outstanding requirements nor to evolve fast enough to comply with the new reality. After a few years of stagnation hundreds and thousands of applications turned into hardly supportable legacy. Even the "RAD" term itself became an offensive word meaning not "ease of use" and "joy of development", but outdated stuff with no future. This situation raised a high demand for modernization.

The desired migration to the mainstream enterprise stack appeared to be surprisingly costly. The same functionality could take 1 day for a Delphi developer and 1 week for a web developer - insane! Obviously, new technology is good for building fully custom and unique applications, but produces a huge overhead for more or less typical LOB systems. Such disbalance showed an uncovered gap on the market of software development tools, which is now occupied by the new generation RADs. The new generation has arisen from the ashes of its predecessors. It means that the majority of representatives of the modern RAD market are not direct descendants of the legacy ones, but were developed from scratch mixing best practices from the past with the mainstream technology. 

## The Foundation of  RAD Platforms

First, let's highlight the main principles of the RAD platforms. In other words, let's see what exactly makes them that efficient in comparison to the traditional development technology stack.

### Architecture and High-level API

Modern RAD platforms address the complexity of the mainstream technology by integrating them into full-stack frameworks with a higher level of abstraction. Such high-level frameworks define a solid architecture of all applications built over them. It is very important to understand that nearly all limitations of your application originate here. How scalable your application can be? Will it be modular? What data stores can be used? Where can it be deployed? What about backward compatibility? ...and many more… 

In return for the introduced limitations, this pre-defined architecture enables fast development of LOB applications by introducing higher level API which lies closer to the business needs. Simply saying, it abstracts developers from the underlying technologies, so they can focus on solving the business tasks.

Such an approach to raising the abstraction level is heavily used in the modern RAD frameworks. There is a list of 5 most notable players taking this path: <a href="https://rubyonrails.org/" target="_blank">Ruby on Rails</a>, <a href="https://grails.org/" target="_blank">Grails</a>, <a href="https://www.djangoproject.com/" target="_blank">Django</a>, <a href="https://www.cuba-platform.com/framework/" target="_blank">CUBA Platform</a>, <a href="https://framework.zend.com/" target="_blank">Zend Framework</a>.

### Typical Functionality

As it was already mentioned RAD platforms are primarily targeted at LOB applications development. This class of applications has a list of common requirements, such as auth, data access restrictions, audit, file storage, full text search, business process management and so on. The RAD platforms deal with such requirements by introducing the corresponding reusable out-of-the-box features and/or add-ons.

This approach is also widely used among modern RADs. So, for this purpose CUBA Platform features its <a href="https://www.jmix.io/cuba-platform/marketplace/" target="_blank">marketplace of add-ons</a>, Ruby on Rails has their <a href="https://rubygems.org/gems/rails/" target="_blank">gems</a>, Grails use <a href="https://plugins.grails.org/" target="_blank">plugins</a> and Django introduces their <a href="https://djangopackages.org/" target="_blank">packages</a>.

### Development Tools

Development tools is probably the most important part that ensures not only high productivity, but also lower barriers to entry, shorter learning track and, of course, joy of use. This turns out to be possible because these tools are narrowly focused on the pre-defined architecture of the platform: programming language, used libraries and underlying frameworks, structure of the application (modules, add-ons, packages) and so on. 

Leveraging the far and wide knowledge about the used architecture enable RAD tools to offer ultimate convenience for developers. To give an idea what exactly they bring to the table let's outline the most common features:

- Intuitive visual designers for the new project bootstrap, project configuration, domain model, UI development, ... 
- Extensive source code generation to automatically scaffold most used and boilerplate snippets
- Smart prompts to avoid error-prone use of the elements, including hot-fixes
- Advanced navigation for application parts and configurations 
- Guided version upgrade procedure to facilitate migration to the latest versions of the platform
- Distributive preparation to make the solution ready for installation

Probably the most vivid example here is the <a href="https://www.embarcadero.com/products/rad-studio" target="_blank">RAD Studio</a> by Embarcadero (former Borland Delphi). Another, but atypical member for the RAD family is <a href="https://www.jhipster.tech/" target="_blank">JHipster</a> - a command line interface tool that mainly takes care about the project bootstrap with a big variety of different options for the initial Java project configuration. CUBA Platform in its turn offers two RAD instruments: <a href="https://www.jmix.io/cuba-platform/tools/" target="_blank">CUBA Studio and CUBA CLI</a>, where the first one is a full scale and very powerful IDE and another one is a lightweight command line interface tool.

## Low Code Development Platforms

If you keep an eye on the modern RAD market and follow its evolution, you couldn't miss a huge buzz storm around the so-called Low Code Development Platforms (LCDP). The whole idea behind Low Codes was expressed in their original slogan - no professional developers will be needed in the near future. They engage not software developers, but business executives. This is the reason why I deliberately didn't mention any of them in the previous chapter. However, we cannot jump over LCDP when talking about RAD as they form quite an interesting phenomenon - development tools against developers. 

Being sold to business executives, they appeal to the main business values: cheaper, faster and with higher quality. Yes, you need to pay hundreds of thousands of dollars annually in licensing, but at the end of the day you win by having no professional-developers (who are very expensive and fickle-minded) and no maintenance for the local infrastructure. They amaze non-technical people by a demonstration, where a sales manager creates a trivial business application with mouse clicks only… It makes the impression that business users (aka citizen developers) will be able to automate (digitize) their own business needs.

From the technical perspective LCDPs are based on the same foundation: predefined architecture and high-level API, ready-to-use typical functionality and development tools. The biggest difference here is the range of applicability of such platforms. To enable non-professional creating enterprise-grade software LCDP vendors narrow down the development process to drawing a flowchart, sacrificing a lot of capabilities in exchange: familiar collaborative development flow, sources control, customizability, extensibility, interoperability, compatibility, performance, auto-testing… As a result, LCDPs are only suitable to build very basic systems.

![text]({{strapiUrl}}/uploads/bbbfed22098d41a0a1f9557c58894909.png)

Nowadays, <a href="https://www.mendix.com/" target="_blank">Mendix</a>, <a href="https://www.outsystems.com/" target="_blank">Outsystems</a> and other LCDPs vendors are trying to build warmer relations with professional developers. But it seems to be a long way ahead, as currently professional developers in their majority do not take low codes seriously for a full bucket of reasons.

## Conclusion

Some would say that "Rapid Application Development Platform" sounds pretty old-fashioned, referring to the outdated technology - I agree that nowadays it has a strong negative connotation. To freshen it up, Gartner came up with new buzz words: Enterprise Low Code Application Platforms and Enterprise High-Productivity Application Platforms. However, drilling down we still see the same principles used to speed up the development of the same class of applications and sharing the same limitations. It looks like a witness protection program for the old-good RAD Platforms, which now live a happy life under their new names.

The modern market of RAD frameworks, tools and platforms is widely diverse, mostly offering fast development of web applications. There is a clear division between two groups: adherents of the traditional path targeted at professional developers and low-code pioneers, engaging the audience of non-professional developers (aka citizen developers). The first group leverages speed and joy of software development mostly by providing higher-level API and code generation - developers simply are kept away from writing boilerplate code and typical functionality. The second one provides powerful runtime environment and visual tools, loved by business users not even for speed of development, but for simplicity they provide - just draw a diagram instead of coding. 

There is no ultimate advice or certain algorithm to find the best RAD tool - it heavily depends on the functional and non-functional requirements for your project. However, I would like to draw your attention to pricing and licensing. With some of the products you are doomed to be paying a fortune - price may vary from 0 up to hundreds of thousands US dollars annually. Especially with low-codes you easily can end-up with 6 digits numbers in your bill - even worse is that you unlikely will be able to go elsewhere because of vendor lock-in.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Tutorial Videos]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-tutorial-videos</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-tutorial-videos</guid>
            <pubDate>Tue, 03 Dec 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/16b425aac9984599a3d55cb611184d2e.png">CUBA team introduces up-to-date video tutorials that aim to reveal the most important and useful features of the platform and its instruments.]]></description>
            <content:encoded><![CDATA[CUBA team introduces up-to-date video tutorials that aim to reveal the most important and useful features of the platform and its instruments.

First of all, we’ve updated the <a href="https://youtu.be/0TjkXYKswLA" target="_blank">Quick Start</a> video guide. Now it guides through CUBA Studio 12 and shows how to develop a very simple, but fully functional conference planner application.

Also, we started a series of <a href="https://www.youtube.com/playlist?list=PLf3PjP4Afu3NZyRcmorxnCvdfPU4UxGcl">CUBA Add-ons tutorials</a>. They show how simple it is to embed the <a href="https://youtu.be/nl-wsnC9K4A" target="_blank">Dashboards</a>, <a href="https://youtu.be/mJsmpIXzcbU" target="_blank">Maps</a>, <a href="https://youtu.be/JqRexrg4mAs" target="_blank">Email Templates</a> and <a href="https://youtu.be/u6U0Y4zNxMc" target="_blank">IMAP</a> add-ons functionality in your application.

And finally our latest guide - a <a href="https://youtu.be/Cv6JnseknSA" target="_blank">short video</a> about deploying an application to the cloud environment through the example of Amazon Elastic Beanstalk.

We plan to continue releasing new tutorial videos for you. We are already working on <a href="https://www.jmix.io/cuba-platform/marketplace/bproc/" target="_blank">BProc</a>, <a href="https://www.jmix.io/cuba-platform/marketplace/webdav/" target="_blank">WebDAV</a> and <a href="https://www.jmix.io/cuba-platform/marketplace/ldap/" target="_blank">LDAP</a> add-ons tutorials and other CUBA short guides, so subscribe to our <a href="https://twitter.com/CubaPlatform" target="_blank">Twitter</a>, <a href="https://www.facebook.com/CUBAplatform/" target="_blank">Facebook</a> or <a href="https://www.linkedin.com/company/cuba-platform/" target="_blank">LinkedIn</a> accounts to keep informed and wait for more video tutorials!
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[TypeScript SDK and React Client Updates ]]></title>
            <link>https://www.jmix.io/cuba-blog/typescript-sdk-and-react-client-updates</link>
            <guid>https://www.jmix.io/cuba-blog/typescript-sdk-and-react-client-updates</guid>
            <pubDate>Tue, 05 Nov 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/c64cd95ea31141a7a906e62fe6af46fd.png">In CUBA, we continuously evaluate more traditional, front-end centric approaches for UI development. We want to share the latest news regarding front-end tools, libraries and code generation.]]></description>
            <content:encoded><![CDATA[In CUBA, we continuously evaluate more traditional, front-end centric approaches for UI development. We want to share the latest news regarding front-end tools, libraries and code generation.

## TypeScript SDK
It's aimed to be used in any JS-based project which communicates with CUBA application using generic <a href="https://github.com/cuba-platform/restapi" target="_blank">REST API</a>, including backends for Node.js.

SDK contains entities (including built-in), enums, views, rest services and queries in order to facilitate working with data in a type-safe manner:

![SDK Showcase]({{strapiUrl}}/uploads/e358ac6b58bd4adfa5002e05cfe0a968.gif)

The SDK can be generated via the command line (see the requirements and usage instructions <a href="https://github.com/cuba-platform/frontend#getting-started-cli" target="_blank">here</a>):

```bash
npx @cuba-platform/front-generator sdk:all
```

You will need typescript 3.2+ in dev dependencies of your project in order to compile the SDK.

More details and examples are available <a href="https://github.com/cuba-platform/frontend#typescript-sdk" target="_blank">here</a>.

## React Client Update

### Standalone Front Application

Having front module inside the main app may result in increased build time, and does not make sense if separate people work on frontend / backend.
Now it's possible to generate front application outside the main project using `@cuba-platform/front-generator` npm package:

```bash
npx @cuba-platform/front-generator react-typescript:app
```

### TypeScript SDK Included in React Client

Now React client contains TypeScript SDK which is placed in `src/cuba` folder.
In order to regenerate SDK to confirm changes in the data model use `npm run update-model` command. 

### Data Components

Data components allow loading, updating and deleting entities. Since implemented as MobX stores, they can be used to seamlessly observe changes and trigger automatic React components re-rendering. Here is the minimal example of `DataCollectionStore` usage:

```typescript
import * as React from "react";
import {observer} from "mobx-react";
import {collection} from "@cuba-platform/react";
import {FavoriteCar} from "../../cuba/entities/mpg$Car";

@observer
class CarList extends React.Component {

  carsData = collection<Car>(Car.NAME, {view: 'car-view', sort: '-updateTs'});

  render() {
    if (this.carsData.status === "LOADING") {
      return 'Loading...';
    }

    return (
      <ul>
        {this.carsData.items.map(car =>
           <li>{car._instanceName}</li>
        )}
      </ul>
    )
  }
 
```

### DataTable Component

We introduced <a href="https://github.com/cuba-platform/frontend#datatable" target="_blank">DataTable</a> React component which is based on Ant.Design's table and allows filtering the displayed data:

![DataTableComponent](https://raw.githubusercontent.com/cuba-platform/front-generator/master/etc/react/data-table-demo.gif)

The DataTable componet works with data using dataCollection component:

```typescript
import {collection, DataTable} from "@cuba-platform/react";
  
  carsDc = collection<Car>(Car.NAME, {view: 'car-view', sort: '-updateTs'});  

  render() {
    return(
      <DataTable dataCollection={this.carsDc}
                 fields={['manufacturer','model','regNumber','purchaseDate','carType']}
                 defaultSort={'-updateTs'}
       />
     )
  }
```


You can generate screens containing data tables using CUBA Studio: 
* Right-click on `Frontend UI` in CUBA project tree and select New > Create Front Component;
* Select `Entity Management` template;
* Select `table` in the List type dropdown.

### Documentation

Basic documentation on the React client will be placed in `README.md` of the scaffolded project and is also available <a href="https://github.com/cuba-platform/frontend#react-client" target="_blank">here</a>.

### Sample

We prepared the React client sample based on Petclinic project. The source code is available <a href="https://github.com/cuba-labs/cuba-petclinic-react" target="_blank">here</a>

![image|652x500](https://raw.githubusercontent.com/cuba-labs/cuba-petclinic-react/master/img/petclinic-react.png)


### Security

Universal REST API provides powerful means of dealing with data, thus you should configure security carefully in case if REST API is enabled. 
Please read the <a href="https://doc.cuba-platform.com/restapi-7.1/#security" target="_blank">corresponding chapter</a> of the REST API manual. In the upcoming release we'll provide a new, stricter denying <a href="https://github.com/cuba-platform/cuba/issues/2493" target="_blank">role type</a>. We also consider providing REST API code generation as an alternative to the universal one.

## Other

### Using System Node.js by default

Since  7.1 release <a href="https://github.com/cuba-platform/cuba-gradle-plugin" target="_blank">the Gradle plugin</a> by default uses Node.js installed in the system. It helps to reduce the amount of time required for creating the front module and improves interop if node/npm is being executed from the command line. Now it's recommended to have Node.js 10+ installed in your system.

When creating a front module, Studio will <a href="https://youtrack.cuba-platform.com/issue/STUDIO-6357" target="_blank">detect</a> the availability of Node.js being executable, and if it's not available, it will add fallback downloading configuration to the `build.gradle`:
```
configure(frontModule) {
  node {
    download = true
  }
```

### Deprecation of Polymer Client

Polymer team released Polymer 3 just as a migration path to be compatible with npm ecosystem and recommended using <a href="https://github.com/Polymer/lit-html" target="_blank">lit-html</a> and <a href="https://lit-element.polymer-project.org/" target="_blank">LitElement</a> for the new projects. Lit-html conceptually utilizes the same principles as React (UI is a function of state), however, it's not battle-proven/well tested yet.  So, at the moment we decided to concentrate our efforts on React as it has a broader ecosystem.

## Try it out

Please use CUBA Studio 12.1+ plugin and Intellij IDEA Ultimate.

We are looking forward to your feedback on our <a href="https://www.cuba-platform.com/discuss/t/typescript-sdk-and-react-client-updates/10368" target="_blank">forum</a>!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Maps for CUBA ]]></title>
            <link>https://www.jmix.io/cuba-blog/new-maps-for-cuba</link>
            <guid>https://www.jmix.io/cuba-blog/new-maps-for-cuba</guid>
            <pubDate>Thu, 01 Aug 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/7755c04b68894fd282ec671d9921e26d.png">Working with spatial data and displaying maps is an inalienable part of many business apps. It can be city or regional information systems, oil-and-gas industry applications, transport infrastructure management systems, as well as delivery services and many more.]]></description>
            <content:encoded><![CDATA[Working with spatial data and displaying maps is an inalienable part of many business apps. It can be city or regional information systems, oil-and-gas industry applications, transport infrastructure management systems, as well as delivery services and many more. Here, in <a href="https://www.cuba-platform.com/" target="_blank">CUBA Platform</a>, besides basic the out-of-the-box functionality for creating such apps, we have a rich ecosystem of <a href="https://www.jmix.io/cuba-platform/marketplace/" target="_blank">additional components</a>. One of those components is Charts and Maps, which can both display charts and enable integrating Google Maps into the visual part of application. Last year Google updated the Maps terms of service which have caused the cost increase, and implied a requirement to have a billing account for using the API. These changes made most of our clients look towards alternative maps providers and encouraged us to develop a new maps add-on.

Now we are happy to introduce a completely new <a href="https://www.jmix.io/cuba-platform/marketplace/maps/" target="_blank">CUBA Maps</a> add-on. 

CUBA Maps is an easy way to enrich your application with visual representation and intuitive manipulation for spatial data. The component operates both with raster and vector data. You are free to use any preferable map provider compatible with the Web Map Service protocol as well as XYZ tile services as raster data. For working with vector data the add-on uses geometry data types (point, polyline, polygon) from <a href="https://locationtech.github.io/jts/" target="_blank">JTS Topology Suite (JTS)</a> — the most popular Java library for working with spatial data. The add-on provides all required features for building a comprehensive geographical information system on CUBA.

This article describes the new features that the new Maps add-on brings and compares it to our previous map component.

## Layer-based structure
The add-on supports the traditional multi-layer structure commonly used in professional GIS systems. Basically, layers can be of raster and vector types. *Raster layers* consist of raster images, while *vector layers* consist of vector geometries.
 
The add-on supports the following types of layers:

- *Tile layer* is used to display tiles provided by XYZ tile services.
- *Web Map Service (WMS)* layer is used to display images from WMS services.
- *Vector layer* contains geo-objects (entities with geometry attributes).

These layers are represented as structural units of maps. For example, one layer serves as a tiled basemap, the second layer contains polygons describing districts, the third layer can consist of geographical points (locations of various objects like customers, shops and so on). Сombining these layers, you build a complete map:

![text]({{strapiUrl}}/uploads/92a34f988afb4b018a101c7574f2cdde.png)
 
This approach gives you full freedom to create well-structured maps with any content. 

CUBA Maps adds to your toolset a new visual component — `GeoMap`. You can define the general map parameters along with the layers in the component’s XML descriptor as in the example below:
```
<maps:geoMap id="map" height="600px" width="100%" center="2.348, 48.853" zoom="8">
    <maps:layers selectedLayer="addressLayer">
        <maps:tile id="tiles" tileProvider="maps_OpenStreetMap"/>
        <maps:vector id="territoryLayer" dataContainer="territoryDc"/>
        <maps:vector id="addressLayer" dataContainer="addressDc" editable="true"/>
    </maps:layers>
</maps:geoMap>
```
Such an approach increases flexibility which the old **Charts and Maps** component lacked. New layers-based approach gives you:

- *Multiple layers.* For example, you can combine tiles provided by different services.
- *Layers provide an abstraction that unites related objects.* In the previous **Charts and Maps** component all map content (like points, polygons, etc) was piled up in the UI component. To structure these objects, project teams had to implement additional logic that handled it.
- *Declarative way of defining the layers.* As it was shown above, you can describe your map structure by defining all layers in the XML descriptor. In most cases it is enough to avoid writing any additional code in the screen controller. In **Charts and Maps** it was almost inevitable to implement some logic in the screen controller.

With Tile layers/WMS layers you are free to use the tile provider that meets your needs. You are not bound to a particular vendor as it was in **Charts and Maps**.

Vector layers enable simple displaying, interactive editing and drawing geo-objects on a map.

It should be mentioned that by default `GeoMap` UI component has a special utility layer — **Canvas**. Canvas provides a straightforward API to display and draw geometries on a map. We will see the examples of using Canvas further in this article.

## Geo-objects
Imagine an entity having a property associated with a geometry (point, polyline, polygon). That’s what we mean by a geo-object. The component simplifies working with geo-objects.

For example, consider the **Address** geo-object:
```
@Entity
public class Address extends StandardEntity {
...
 
 
  @Column(name = "LOCATION")
  @Geometry
  @MetaProperty(datatype = "GeoPoint")
  @Convert(converter = CubaPointWKTConverter.class)
  protected Point location;

 
  ...
}
```
It has a property `location` of the `org.locationtech.jts.geom.Point` type that comes from the JTS Topology Suite (JTS) library. The add-on supports the following JTS geometry types:

- `org.locationtech.jts.geom.Point` — point.
- `org.locationtech.jts.geom.LineString` — polyline.
- `org.locationtech.jts.geom.Polygon` — polygon.

The `location` property is annotated with `@Geometry` annotation. This annotation marks the property to be used when displaying the entity on a map. The geometry property also has the following annotations:

- `@MetaProperty` — specifies the corresponding <a href="https://doc.cuba-platform.com/manual-latest/datatype.html" target="_blank">datatype</a> for the attribute. Datatypes are used by CUBA framework for converting values to and from strings.
- `@Convert` — specifies a JPA converter for a persistent attribute. A JPA converter performs type conversion between the database and Java representation of an attribute.

The component comes with a set of spatial datatypes and JPA converters. For more information please refer to the component’s <a href="https://doc.cuba-platform.com/maps-1.0/" target="_blank">documentation</a>. It is possible to specify your own implementation of the JPA converter, which means that you can work with various providers of spatial data (for example, <a href="https://postgis.net/" target="_blank">PostGIS</a>).

Thus, to turn your entity into a geo-object, you should declare a meta property of a JTS geometry type and annotate it with `@Geometry`. Another option is to create a non-persistent geometry property by exposing getter/setter methods. It can be helpful if you don't want to change your model and regenerate DDL scripts.

For example, consider the **Address** entity having latitude/longitude in separate fields:
```
import com.haulmont.addon.maps.gis.utils.GeometryUtils;
...
 
@Entity
public class Address extends StandardEntity {
...
 
 
  @Column(name = "LATITUDE")
  protected Double latitude;
 
  @Column(name = "LONGITUDE")
  protected Double longitude;
 
 
...
   
  @Geometry
  @MetaProperty(datatype = "GeoPoint", related = {"latitude", "longitude"})
  public Point getLocation() {
    if (getLatitude() == null || getLongitude() == null) {
        return null;
    }
    return GeometryUtils.createPoint(getLongitude(), getLatitude());
  }
 
  @Geometry
  @MetaProperty(datatype = "GeoPoint")
  public void setLocation(Point point) {
    Point prevValue = getLocation();
    if (point == null) {
        setLatitude(null);
        setLongitude(null);
    } else {
        setLatitude(point.getY());
        setLongitude(point.getX());
    }
    propertyChanged("location", prevValue, point);
  }
 
  ...
}
```
If you take the second option, make sure to invoke `propertyChanged` method in the setter, because the component automatically updates the geometry on a map after this event was fired.

Now that we have prepared our geo-object class, we can add instances of this class to the vector layer. *Vector layer* is a data-aware component acting as a connector between data (geo-objects) and a map. To bind geo-objects to the layer you need to pass a datacontainer (or datasource in case of using in legacy screens) to the vector layer. This can be accomplished in the XML descriptor:
```
<maps:geoMap id="map">
    <maps:layers>
        ...
        <maps:vector id="addressesLayer" dataContainer="addressesDc"/>
    </maps:layers>
</maps:geoMap>
```
As a result, the instances of the `Address` class located in the `addressesDc` data container will be displayed on the map.

Let’s consider a basic task of creating an editor screen for a geo-object with the map, where you can edit a geometry. To achieve this, you need to declare the `GeoMap` UI component in the screen XML descriptor and define a vector layer connected with the editing object.
```
<maps:geoMap id="map" height="600px" width="100%" center="2.348, 48.853" zoom="8">
    <maps:layers selectedLayer="addressLayer">
        <maps:tile ..."/>
        <maps:vector id="addressLayer" dataContainer="addressDc" editable="true"/>
    </maps:layers>
</maps:geoMap>
```
By marking the layer as editable you enable interactive geo-object editing. If geometry property of the editing geo-object has the empty value, then the map will be automatically turned into the drawing mode. As you can see, the only thing you need to do is to declare a vector layer and provide a datacontainer to it. 

And this is it. If we had used **Charts and Maps** for solving this problem, it would be necessary to write a pretty big amount of code in the screen controller in order to achieve this functionality. The new **Maps** component provides a really straightforward way of solving such tasks.

## Canvas

Sometimes you do not want to work with entities. Instead, you want a simple API for easy adding and drawing geometries on a map like it was in **Charts and Maps**. For this purpose, the `GeoMap` UI component has a special layer called *Canvas*. It is a utility layer that a map has by default and which provides a straightforward API for adding and drawing geometries on a map. You can get the Canvas by calling the `map.getCanvas() method`.

Next, we will overview some basic tasks, how they were solved in Charts and Maps and how we can do the same using the Canvas.

### Displaying geometries on a map

In **Charts and Maps** geometry objects were created using the map UI component as a factory and then added to the map:
```
Marker marker = map.createMarker();
GeoPoint position = map.createGeoPoint(lat, lon);
marker.setPosition(position);
map.addMarker(marker);
```
New **Maps** add-on works with geometry classes from the JTS library:
```
CanvasLayer canvasLayer = map.getCanvas();
Point point = address.getLocation();
canvasLayer.addPoint(point);
```

### Editing geometries

In **Charts and Maps** you were able to mark geometry objects as editable. When these geometries were modified via UI, corresponding events were fired:
```
Marker marker = map.createMarker();
GeoPoint position = map.createGeoPoint(lat, lon);
marker.setPosition(position);
marker.setDraggable(true);
map.addMarker(marker);

map.addMarkerDragListener(event -> {
        // do something
});
```
In **Maps**, when you add a JTS geometry on the Canvas, the method returns you a special object that represents this geometry on a map: `CanvasLayer.Point`, `CanvasLayer.Polyline` or `CanvasLayer.Polygon`. Using this object you can set multiple geometry parameters using fluent API, subscribe to geometry-related events, or use this object when you want to remove the geometry from the Canvas.
```
CanvasLayer canvasLayer = map.getCanvas();
CanvasLayer.Point location = canvasLayer.addPoint(address.getLocation());
location.setEditable(true)
        .setPopupContent(address.getName())
        .addModifiedListener(modifiedEvent ->
             address.setLocation(modifiedEvent.getGeometry()));
```

### Drawing geometries

In **Charts and Maps** there was an auxiliary drawing component — `DrawingOptions`. It was used to enable drawing capabilities in a map. After a geometry was drawn the corresponding event was fired:
```
DrawingOptions options = new DrawingOptions();
PolygonOptions polygonOptions = new PolygonOptions(true, true, "#993366", 0.6);
ControlOptions controlOptions = new ControlOptions(
Position.TOP_CENTER, Arrays.asList(OverlayType.POLYGON));
options.setEnableDrawingControl(true);
options.setPolygonOptions(polygonOptions);
options.setDrawingControlOptions(controlOptions);
options.setInitialDrawingMode(OverlayType.POLYGON);
map.setDrawingOptions(options);
 
 
map.addPolygonCompleteListener(event -> {
    //do something
});
```
In **Maps**, Canvas provides a set of methods for drawing geometries. For example, to draw a polygon invoke `canvas.drawPolygon()` method. After this method is called the map will turn into the drawing mode. The method accepts `Consumer<CanvasLayer.Polygon>` function, in which you can perform additional actions with the drawn polygon.
```
canvasLayer.drawPolygon(polygon -> {
    territory.setPolygon(polygon.getGeometry());
});
```

## Features for geoanalysis

### Clustering

Another useful feature that comes with the new **Maps** add-on is clustering of points. When a layer contains a large number of points you can enable clustering to group nearby points into clusters and make the map more good-looking:

![text]({{strapiUrl}}/uploads/3232f53333dc4773b18c70df35837a5f.jpg)

Clustering can be enabled by adding the `cluster` element inside the `vector` in the XML descriptor:
 ```
<maps:vector id="locations" dataContainer="locationsDc" >
  <maps:cluster/>
</maps:vector>
 ```
You can also enable clustering based on the point's weight specified by geo-object's property:
 ```
<maps:vector id="orders" dataContainer="ordersDc" >
  <maps:cluster weightProperty="amount"/>
</maps:vector>
```

### Heatmaps

Heatmaps provide a visual representation of data density across a set of geographical points. `GeoMap` UI component provides a method for adding a heatmap overlay to a map: `addHeatMap(Map<Point, Double> intensityMap)`.

![text]({{strapiUrl}}/uploads/1ab1f3ec0a88487e8f425cead4f76cc0.jpg)

## Conclusion

Working with spatial data is essential for many business applications. **CUBA Maps** provides your CUBA application with all required features to achieve this functionality.

The layer-based structure lets you easily create maps with any content. With Tile layers/WMS layers you can use any preferable provider for your basemap. Vector layers help to effectively work with a group of related geo-objects. Canvas layer provides a straightforward API to display and draw geometries on a map.

The add-on integrates spatial types from the JTS library, which makes it compatible with many other frameworks (for example, <a href="https://geotools.org/" target="_blank">GeoTools</a>) to solve a wide range of GIS tasks.

We hope you enjoy the add-on and we are looking forward to your feedback!

## Video Tutorial

<iframe width="770" height="433" src="https://youtube.com/embed/mJsmpIXzcbU" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Maintenance releases for CUBA 6 versions]]></title>
            <link>https://www.jmix.io/cuba-blog/maintenance-releases-for-cuba-6-versions</link>
            <guid>https://www.jmix.io/cuba-blog/maintenance-releases-for-cuba-6-versions</guid>
            <pubDate>Wed, 05 Jun 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/ab2df364c21147068be63dbda0d44855.jpg">Not so long ago we've announced the major release of CUBA Platform - CUBA 7. Nevertheless, CUBA Team provides support for the previous versions of the platform. We're going to continue releasing 6.2-6.10 versions with security and bug fixes.

Don't miss our latest maintenance releases with [security fixes](https://www.cuba-platform.com/discuss/t/maintenance-releases-for-6-2-6-10-versions-with-security-fixes) and [fixes for Firefox 67](https://www.cuba-platform.com/discuss/t/maintenance-releases-of-6-2-7-0-versions-with-fixes-for-firefox-67).]]></description>
            <content:encoded><![CDATA[Not so long ago we've announced the major release of CUBA Platform - CUBA 7. Nevertheless, CUBA Team provides support for the previous versions of the platform. We're going to continue releasing 6.2-6.10 versions with security and bug fixes.

Don't miss our latest maintenance releases with <a href="https://www.cuba-platform.com/discuss/t/maintenance-releases-for-6-2-6-10-versions-with-security-fixes" target="_blank">security fixes</a> and <a href="https://www.cuba-platform.com/discuss/t/maintenance-releases-of-6-2-7-0-versions-with-fixes-for-firefox-67" target="_blank">fixes for Firefox 67</a>.

The last fixes are caused by the breaking change in Firefox 67.0 that overrides any variable with name `u2f`. This breaks many Vaadin and GWT applications because the minifier quite quickly starts using `u2f` as a function or variable name. That’s why we’ve released the following maintenance versions of the platform:

- 6.2.10
- 6.3.8
- 6.4.7
- 6.5.10
- 6.6.8
- 6.7.15
- 6.8.18
- 6.9.10
- 6.10.10

Follow our blog, forum and social networks to keep informed about the latest releases. Thank you for being a part of CUBA Platform Community!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Fetching data with ORM is easy! Is it? ]]></title>
            <link>https://www.jmix.io/cuba-blog/fetching-data-with-ORM-is-easy-is-it</link>
            <guid>https://www.jmix.io/cuba-blog/fetching-data-with-ORM-is-easy-is-it</guid>
            <pubDate>Thu, 16 May 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/9e00ba9ca04843c48e050a9bde9aa37a.jpg">Almost any system operates with external data stores in some way. In most of the cases, it is a relational database and very often data fetching is delegated to some ORM implementation. ORM covers a lot of routine and brings along a few new abstractions in return.]]></description>
            <content:encoded><![CDATA[## Introduction

Almost any system operates with external data stores in some way. In most of the cases, it is a relational database and very often data fetching is delegated to some ORM implementation. ORM covers a lot of routine and brings along a few new abstractions in return. 

Martin Fowler wrote an interesting <a href="https://dzone.com/articles/martin-fowler-orm-hate" target="_blank">article</a> about ORM and one of the key thoughts there is  “ORMs help us deal with a very real problem for most enterprise applications. ... They aren't pretty tools, but then the problem they tackle isn't exactly cuddly either. I think they deserve a little more respect and a lot more understanding”.   

In <a href="https://cuba-platform.com/" target="_blank">CUBA</a> framework we use ORM very heavily and know a lot about its limitations since we have various kinds of projects all over the world. There are a lot of things that can be discussed, but we will focus on one of them: lazy vs eager data fetch. We’ll talk about different approaches to data fetch (mostly within JPA API and Spring), how we deal with it in CUBA and what RnD work we do to improve ORM layer in CUBA. We will have a look at essentials that might help developers to not hit issues with terrible performance using ORMs. 

## Fetching Data: Lazy way or Eager way?

If your data model contains only one entity, there will be no issues with using ORM. Let’s have a look at the example. We have a user who has ID and Name:

```java
public class User {
   @Id
   @GeneratedValue
   private int id;
   private String name;

   //Getters and Setters here
}
```
To fetch it we just need to ask EntityManager nicely:

```java
EntityManager em = entityManagerFactory.createEntityManager();
User user = em.find(User.class, id);
```
Things get interesting when we have one-to-many relation between entities:
```java
public class User {
   @Id
   @GeneratedValue
   private int id;
   private String name;
   @OneToMany
   private List<Address> addresses;

   //Getters and Setters here
}
```
If we want to fetch a user record from the database, a question arises: “Should we fetch an address too?”. And the “right” answer will be: “It depends”. In some use cases, we may need an address in some of them - not. Usually, an ORM provides two options for fetching data: lazy and eager. Most of them set the lazy fetch mode by default. And when we write the following code:

```java
EntityManager em = entityManagerFactory.createEntityManager();
User user = em.find(User.class, 1);
em.close();
System.out.println(user.getAddresses().get(0));
```
We get so-called ```“LazyInitException”``` which confuses ORM rookies very much. And here we need to explain the concept on an “Attached” and “Detached” objects as well as tell about database sessions and transactions. 

OK then, an entity instance should be attached to a session so we should be able to fetch details attributes. In this case, we got another problem - transactions are getting longer, therefore, a risk of getting a deadlock increase. And splitting our code to a chain of short transactions may cause “death of million mosquitos” for the database due to an increased number of very short separate queries.
 
As it was said, you may or may not need Addresses attribute fetched, therefore you need to “touch” the collection only in some use cases, adding more conditions. Hmmmm…. Looks like it’s getting complex.

OK, will another fetch type help?

```java
public class User {
   @Id
   @GeneratedValue
   private int id;
   private String name;
   @OneToMany(fetch = FetchType.EAGER)
   private List<Address> addresses;

   //Getters and Setters here
}
```
Well, not exactly. We’ll get rid of the annoying lazy init exception and should not check whether an instance is attached or detached. But we got a performance problem, because, again, we don’t need Addresses for all cases, but select them always. Any other ideas? 

## Spring JDBC

Some developers become so annoyed with ORM that they switch to “semi-automatic” mappings using Spring JDBC. In this case, we create unique queries for unique use cases and return objects that contain attributes valid for a particular use case only. 

It gives us great flexibility. We can get only one attribute:

```java
String name = this.jdbcTemplate.queryForObject(
       "select name from t_user where id = ?",
       new Object[]{1L}, String.class);
```
Or the whole object:
```java
User user = this.jdbcTemplate.queryForObject(
       "select id, name from t_user where id = ?",
       new Object[]{1L},
       new RowMapper<User>() {
           public User mapRow(ResultSet rs, int rowNum) throws SQLException {
               User user = new User();
               user.setName(rs.getString("name"));
               user.setId(rs.getInt("id"));
               return user;
           }
       });
```
You can fetch addresses too using ResultSetExtractor, but it involves writing some extra code and you should know how to write SQL joins to avoid <a href="https://www.javacodegeeks.com/2018/04/jpa-tips-avoiding-the-n-1-select-problem.html" target="_blank">n+1 select problem</a>. 

Well, it’s getting complex again. You control all the queries and you control mapping, but you have to write more code, learn SQL and know how database queries are executed. Though I think knowing SQL basics is a necessary skill for almost every developer, some of them do not think so and I’m not going to argue with them. Knowing x86 assembler is not a vital skill for everyone nowadays too. Let’s just think about how we can simplify development. 

## JPA EntityGraph

Let’s make a step back and try to understand what we’re going to achieve? It seems like all we need to do is to tell exactly which attributes we’re going to fetch in different use cases. Let’s do it then! JPA 2.1 has introduced a new API - Entity Graph. The idea behind this API is simple - you just write several annotations that describe what should be fetched. Let’s have a look at the example:

```java
@Entity
@NamedEntityGraphs({
       @NamedEntityGraph(name = "user-only-entity-graph"),
       @NamedEntityGraph(name = "user-addresses-entity-graph",
               attributeNodes = {@NamedAttributeNode("addresses")})
       })
public class User {
   @Id
   @GeneratedValue
   private int id;
   private String name;
   @OneToMany(fetch = FetchType.LAZY)
   private Set<Address> addresses;

   //Getters and Setters here

}
```
For this entity we’ve described two entity graphs - the ```user-only-entity-graph``` does not fetch the ```Addresses``` attribute (which is marked as lazy), whilst the second graph instructs the ORM to select addresses. If we mark an attribute as eager, entity graph settings will be ignored and the attribute will be fetched.

So, starting from JPA 2.1 you can select entities in the following way:

```java
EntityManager em = entityManagerFactory.createEntityManager();
EntityGraph graph = em.getEntityGraph("user-addresses-entity-graph");
Map<String, Object> properties = Map.of("javax.persistence.fetchgraph", graph);
User user = em.find(User.class, 1, properties);
em.close();
```
This approach greatly simplifies a developer’s work, there is no need to “touch” lazy attributes and create long transactions. The great thing is that the entity graph can be applied at the SQL generation level, so no extra data is fetched to Java application from the database. But there is a problem still. We cannot say which attributes were fetched and which weren’t. There is an API for this, you can check attributes using ```PersistenceUnit``` class:

```java
PersistenceUtil pu = entityManagerFactory.getPersistenceUnitUtil();
System.out.println("User.addresses loaded: " + pu.isLoaded(user, "addresses"));
```
But it is pretty boring. Can we simplify it and just do not show unfetched attributes?

## Spring Projections

Spring Framework provides a fantastic facility called <a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections" target="_blank">Projections</a> (and it’s different from Hibernate’s <a href="https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#criteria-projection" target="_blank">Projections</a>). If we want to fetch only some properties of an entity, we can specify an interface and Spring will select interface “instances” from a database. Let’s have a look at the example. If we define the following interface:

```java
interface NamesOnly {
   String getName();
}
```
And then define a Spring JPA repository to fetch our User entities:
```java
interface UserRepository extends CrudRepository<User, Integer> {
   Collection<NamesOnly> findByName(String lastname);
}
```
In this case after the invocation of the findByName method we just won’t be able to access unfetched attributes! The same principle applies to detail entity classes too. So you can fetch both master and detail records this way. Moreover, in the most cases Spring generates “proper” SQL and fetches only attributes specified in the projection, i.e. projections work like entity graph descriptions.
 
It is a very powerful concept, you can use SpEL expressions, use classes instead of interfaces, etc. There is more information in the <a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections" target="_blank">documentation</a> you can check it if you’re interested.
 
The only problem with Projections is that under the hood they are implemented as maps, hence read-only. Therefore, thought you can define a setter method for a projection, you won’t be able to save changes using neither CRUD repositories nor EntityManager. You can treat projections as DTOs, and you have to write your own DTO-to-entity conversion code.

## CUBA Implementation

From the beginning of CUBA framework development, we tried to optimize the code that works with a database. In the framework, we use <a href="https://www.eclipse.org/eclipselink/" target="_blank">EclipseLink</a> to implement data access layer API. The good thing about EclipseLink - it supported partial entity load from the beginning, that’s why we chose it over Hibernate in the first place. In this ORM, you could specify which exactly attributes should be loaded before JPA 2.1 had become a standard. Therefore we added our internal “Entity Graph”-like concept to our framework - <a href="https://doc.cuba-platform.com/manual-7.0/views.html" target="_blank">CUBA Views</a>. Views are pretty powerful - you can extend them, combine, etc. The second reason behind CUBA Views creation - we wanted to use short transactions, and focus on working mostly with detached objects, otherwise, we could not make rich web UI fast and responsive. 

In CUBA view descriptions are stored in XML file and look like this:
```xml
<view class="com.sample.User"
     extends="_local"
     name="user-minimal-view">
   <property name="name"/>
   <property name="addresses"
             view="address-street-only-view"/>
   </property>
</view>
```
This view instructs CUBA DataManager to fetch User entity with its local name attribute and fetch addresses applying address-street-only-view while fetching them (important!) at the query level. When a view is defined you could apply it to get entities using DataManager class:

```java
List<User> users = dataManager.load(User.class).view("user-edit-view").list();
```
It works like a charm, and saves a lot of network traffic on not loading unused attributes but like in JPA Entity Graph there is a small issue: we cannot say which attributes of the User entity were loaded. And in CUBA we have annoying ```“IllegalStateException: Cannot get unfetched attribute [...] from detached object”```. Like in JPA, you can check whether an attribute unfetched, but writing these checks for every entity being fetched is a boring job and developers are not happy with it. 

## CUBA View Interfaces PoC

And what if we could take the best of two worlds? We decided to implement so-called entity interfaces that utilize Spring’s approach, but those interfaces are translated into CUBA views during application startup and then can be used in DataManager. The idea is pretty simple: you define an interface (or a set of interfaces) that specify entity graph. It looks like Spring Projections and works like Entity Graph:

```java
interface UserMinimalView extends BaseEntityView<User, Integer> {
   String getName();
   void setName(String val);
   List<AddressStreetOnly> getAddresses();

   interface AddressStreetOnly extends BaseEntityView<Address, Integer> {
      String getStreet();
      void setStreet(String street);
   }
}
```
Note that ```AddressStreetOnly``` interface can be nested if it is used only in one case. 

During CUBA Application startup (in fact, it is mostly Spring Context Initialization), we create a programmatic representation for CUBA views and store them in an internal repository bean in Spring context.

After that we need to tweak the DataManager, so it can accept class names in addition to CUBA View string names and then we simply pass interface class: 

```java
List<User> users = dataManager.loadWithView(UserMinimalView.class).list();
```
We generate proxies implementing entity view for each instance fetched from the database as hibernate does. And when you try to get an attribute’s value, the proxy forwards the invocation to the real entity.

With this implementation we’re trying to kill two birds with one stone:

* The data that is not stated in the interface is not loaded to the Java application code, thus saving server resources
* A developer uses only properties that were fetched, therefore, no more “UnfetchedAttribute” errors (aka ```LazyInitException``` in Hibernate).

In contrast to Spring Projections, Entity Views wrap entities and implement CUBA’s Entity interface, therefore they can be treated as entities: you can update a property and save changes to the database. 

The “third bird” here - you can define a “read-only” interface that contains only getters, completely preventing entities from modifications at the API level. 

Also, we can implement some operations on the detached entity like this user’s name conversion to lowercase:

```java
@MetaProperty
default String getNameLowercase() {
   return getName().toLowerCase();
}
```
In this case, all calculated attributes can be moved from the entity model, so you don’t mix data fetch logic with use case-specific business logic. 

Another interesting opportunity - you can inherit interfaces. This gives you a possibility to prepare several views with a different set of attributes and then mix them if needed. For example, you can have one interface that contains the user’s name and email and another one, that contains name and addresses. And if you need a third view interface that should contain a name, email, and addresses, you can do it just by combining both - thanks to multiple inheritance of interfaces in Java. Please note that you can pass this third interface to methods that consume either first or second interface, OOP principles work here as usual. 

We’ve also implemented entity conversion between views - each entity view has reload() method that accepts another view class as a parameter:

```java
UserFullView userFull = userMinimal.reload(UserFullView.class);
```
UserFullView may contain additional attributes, so the entity will be reloaded from the database. And entity reload is a lazy process, it will be performed only when you try to get an entity attribute value. We did this on purpose because in CUBA we have a “web” module that renders rich UI and may contain custom REST controllers. In this module, we use the same entities, and it can be deployed on a separate server. Therefore, each entity reload causes an additional request to the database via the core module (a.k.a middleware). So, by introducing lazy entity reload we save some network traffic and database queries. 

The PoC can be downloaded from the <a href="https://github.com/cuba-rnd/entity-views-sample" target="_blank">GitHub</a> - feel free to play with it.

## Conclusion

ORMs are going to be massively used in enterprise applications in the near future. We just have to provide something that will convert database rows into Java objects. Of course in complex, high-load applications we’ll continue seeing unique solutions, but ORM will live as long as RDBMSes will.
 
In CUBA framework we’re trying to simplify ORM use to make it as painless for developers as possible. And in the next versions, we’re going to introduce more changes. I’m not sure whether those will be view interfaces or something else, but I’m pretty sure with one thing - working with ORM in the next version with CUBA will be simplified. ]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Analyzing the Code of CUBA Platform with PVS-Studio]]></title>
            <link>https://www.jmix.io/cuba-blog/analyzing-cuba-platform-with-pvs-studio</link>
            <guid>https://www.jmix.io/cuba-blog/analyzing-cuba-platform-with-pvs-studio</guid>
            <pubDate>Wed, 24 Apr 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/ee59786f48494cc49cd771ce6f054bbf.png">Java developers have access to a number of useful tools that help to write high-quality code such as the powerful IDE IntelliJ IDEA, free analyzers SpotBugs, PMD, and the like. The developers working on CUBA Platform have already been using all of these, and this review will show how the project can benefit even more from the use of the static code analyzer PVS-Studio.]]></description>
            <content:encoded><![CDATA[### Comment by CUBA Platform developers

Any large project surely has bugs in it. Knowing that, we gladly agreed when the PVS-Studio team offered to check our project. The CUBA repository contains forks of some of the third-party OSS libraries licensed under Apache 2, and it looks like we should pay more attention to that code as the analyzer found quite a number of problems in those sources. We currently use SpotBugs as our primary analyzer, and it fails to notice some of the big bugs reported by PVS-Studio. It seems we should write some additional diagnostics ourselves. Anyway, many thanks to the PVS-Studio team for the job.

<div class="citation"><div class="citation-line"></div><div class="citation-icon"></div></div>

Author – Svyatoslav Razmyslov, original post is at <a href="https://www.viva64.com/en/b/0626/" target="_blank">PVS-Studio blog</a>

Java developers have access to a number of useful tools that help to write high-quality code such as the powerful IDE IntelliJ IDEA, free analyzers SpotBugs, PMD, and the like. The developers working on CUBA Platform have already been using all of these, and this review will show how the project can benefit even more from the use of the static code analyzer PVS-Studio.


### A few words about the analyzer

<a href="https://www.viva64.com/en/pvs-studio/" target="_blank">PVS-Studio</a> is a tool for detecting bugs and potential security vulnerabilities in the source code of programs written in C, C++, C#, and Java. The analyzer runs on 64-bit Windows, Linux, and macOS systems. To make things easier for Java programmers, we developed plugins for Maven, Gradle, and IntelliJ IDEA. I checked the project using the Gradle plugin, and it went off without a hitch.

### Errors in conditions

**Warning 1**

<a href="https://www.viva64.com/en/w/v6007/" target="_blank">V6007</a> Expression 'StringUtils.isNotEmpty("handleTabKey")' is always true. SourceCodeEditorLoader.java(60)

```java
@Override
public void loadComponent() {
  ....
  String handleTabKey = element.attributeValue("handleTabKey");
  if (StringUtils.isNotEmpty("handleTabKey")) {
    resultComponent.setHandleTabKey(Boolean.parseBoolean(handleTabKey));
  }
  ....
}
```

The attribute value extracted from the element is not checked. Instead, the _isNotEmpty_ function gets a string literal as its argument rather than the variable _handleTabKey_.

A similar error found in the file AbstractTableLoader.java:

* V6007 Expression 'StringUtils.isNotEmpty("editable")' is always true. AbstractTableLoader.java(596)

**Warning 2**

<a href="https://www.viva64.com/en/w/v6007/" target="_blank">V6007</a> Expression 'previousMenuItemFlatIndex >= 0' is always true. CubaSideMenuWidget.java(328)

```java
protected MenuItemWidget findNextMenuItem(MenuItemWidget currentItem) {
  List<MenuTreeNode> menuTree = buildVisibleTree(this);
  List<MenuItemWidget> menuItemWidgets = menuTreeToList(menuTree);

  int menuItemFlatIndex = menuItemWidgets.indexOf(currentItem);
  int previousMenuItemFlatIndex = menuItemFlatIndex + 1;
  if (previousMenuItemFlatIndex >= 0) {
      return menuItemWidgets.get(previousMenuItemFlatIndex);
  }
  return null;
}
```

The _indexOf_ function will return _-1_ if the element is not found in the list. The value _1_ is then added to the index, which disguises the problem with the absent element. Another potential problem has to do with the fact that the _previousMenuItemFlatIndex_ variable will always be greater than or equal to zero. For example, if the _menuItemWidgets_ list is found to be empty, the program will end up with an array overrun.

**Warning 3**

<a href="https://www.viva64.com/en/w/v6009/" target="_blank">V6009</a> The 'delete' function could receive the '-1' value while non-negative value is expected. Inspect argument: 1. AbstractCollectionDatasource.java(556)

```java
protected DataLoadContextQuery createDataQuery(....) {
  ....
  StringBuilder orderBy = new StringBuilder();
  ....
  if (orderBy.length() > 0) {
      orderBy.delete(orderBy.length() - 2, orderBy.length());
      orderBy.insert(0, " order by ");
  }
  ....
}
```

The last two characters of the _orderBy_ buffer are deleted if the total number of elements is greater than zero, i.e. if the string contains at least one character. However, the start position from where the deletion begins is offset by 2. So, if _orderBy_ happens to contain one character, attempting to delete it will raise a _StringIndexOutOfBoundsException_.

**Warning 4**

<a href="https://www.viva64.com/en/w/v6013/" target="_blank">V6013</a> Objects 'masterCollection' and 'entities' are compared by reference. Possibly an equality comparison was intended. CollectionPropertyContainerImpl.java(81)

```java
@Override
public void setItems(@Nullable Collection<E> entities) {
  super.setItems(entities);
  Entity masterItem = master.getItemOrNull();
  if (masterItem != null) {
    MetaProperty masterProperty = getMasterProperty();
    Collection masterCollection = masterItem.getValue(masterProperty.getName());
    if (masterCollection != entities) {
      updateMasterCollection(masterProperty, masterCollection, entities);
    }
  }
}
```

In the _updateMasterCollection_ function, the values from entities are copied to _masterCollection_. One line earlier, the collections have been compared by reference, but the programmer probably intended it to be a comparison by value.

**Warning 5**

<a href="https://www.viva64.com/en/w/v6013/" target="_blank">V6013</a> Objects 'value' and 'oldValue' are compared by reference. Possibly an equality comparison was intended. WebOptionsList.java(278)

```java
protected boolean isCollectionValuesChanged(Collection<I> value,
                                            Collection<I> oldValue) {
  return value != oldValue;
}
```

This case is similar to the previous one. The collections are compared in the _isCollectionValuesChanged_ function, and reference comparison is perhaps not what was intended here either.

### Redundant conditions

**Warning 1**

<a href="https://www.viva64.com/en/w/v6007/" target="_blank">V6007</a> Expression 'mask.charAt(i + offset) != placeHolder' is always true. DatePickerDocument.java(238)

```java
private String calculateFormattedString(int offset, String text) .... {
  ....
  if ((mask.charAt(i + offset) == placeHolder)) {         // <=
    ....
  } else if ((mask.charAt(i + offset) != placeHolder) &&  // <=
             (Character.isDigit(text.charAt(i)))) {
    ....
  }
  ....
}
```

The second condition checks an expression that is opposite to the one checked in the first condition. The latter can, therefore, be safely removed to shorten the code.

<a href="https://www.viva64.com/en/w/v6007/" target="_blank">V6007</a> Expression 'connector == null' is always false. HTML5Support.java(169)

```java
private boolean validate(NativeEvent event) {
  ....
  while (connector == null) {
    widget = widget.getParent();
    connector = Util.findConnectorFor(widget);
  }

  if (this.connector == connector) {
      return true;
  } else if (connector == null) {             // <=
      return false;
  } else if (connector.getWidget() instanceof VDDHasDropHandler) {
      return false;
  }
  return true;
}
```

After leaving the _while_ loop, the value of the _connector_ variable won't be equal to _null_, so the redundant check can be deleted.

Another suspicious warning of this type that needs to be examined:

* V6007 Expression 'StringUtils.isBlank(strValue)' is always true. Param.java(818)

### Unreachable code in tests

<a href="https://www.viva64.com/en/w/v6019/" target="_blank">V6019</a> Unreachable code detected. It is possible that an error is present. TransactionTest.java(283)

```java
private void throwException() {
  throw new RuntimeException(TEST_EXCEPTION_MSG);
}

@Test
public void testSuspendRollback() {
  Transaction tx = cont.persistence().createTransaction();
  try {
    ....
    Transaction tx1 = cont.persistence().createTransaction();
    try {
      EntityManager em1 = cont.persistence().getEntityManager();
      assertTrue(em != em1);
      Server server1 = em1.find(Server.class, server.getId());
      assertNull(server1);
      throwException();        // <=
      tx1.commit();            // <=
    } catch (Exception e) {
      //
    } finally {
      tx1.end();
    }

    tx.commit();
  } finally {
    tx.end();
  }
}
```

The _throwException_ function throws an exception that prevents execution of the call of _tx1.commit_. Those two lines should be swapped for the code to work properly.

There were a few similar problems in other tests too:

* V6019 Unreachable code detected. It is possible that an error is present. TransactionTest.java(218)
* V6019 Unreachable code detected. It is possible that an error is present. TransactionTest.java(163)
* V6019 Unreachable code detected. It is possible that an error is present. TransactionTest.java(203)
* V6019 Unreachable code detected. It is possible that an error is present. TransactionTest.java(137)
* V6019 Unreachable code detected. It is possible that an error is present. UpdateDetachedTest.java(153)
* V6019 Unreachable code detected. It is possible that an error is present. EclipseLinkDetachedTest.java(132)
* V6019 Unreachable code detected. It is possible that an error is present. PersistenceTest.java(223)

### Suspicious arguments

**Warning 1**

<a href="https://www.viva64.com/en/w/v6023/" target="_blank">V6023</a> Parameter 'salt' is always rewritten in method body before being used. BCryptEncryptionModule.java(47)

```java
@Override
public String getHash(String content, String salt) {
  salt = BCrypt.gensalt();
  return BCrypt.hashpw(content, salt);
}
```

In cryptography, _salt_ is a data string that you pass along with the password to a hash function. It is mainly used to protect the program against dictionary attacks and rainbow table attacks, as well as to obscure identical passwords. More here: <a href="https://en.wikipedia.org/wiki/Salt_(cryptography)" target="_blank">Salt (cryptography)</a>.
In this function, the passed string is overwritten right after entering. Ignoring the value passed to the function is a potential vulnerability.

**Warning 2**

This function triggered two warnings at once:

* <a href="https://www.viva64.com/en/w/v6023/" target="_blank">V6023</a> Parameter 'offsetWidth' is always rewritten in method body before being used. CubaSuggestionFieldWidget.java(433)
* <a href="https://www.viva64.com/en/w/v6023/" target="_blank">V6023</a> Parameter 'offsetHeight' is always rewritten in method body before being used. CubaSuggestionFieldWidget.java(433)

```java
@Override
public void setPosition(int offsetWidth, int offsetHeight) {
  offsetHeight = getOffsetHeight();
  ....
  if (offsetHeight + getPopupTop() > ....)) {
    ....
  }
  ....
  offsetWidth = containerFirstChild.getOffsetWidth();
  if (offsetWidth + getPopupLeft() > ....)) {
      ....
  } else {
      left = getPopupLeft();
  }
  setPopupPosition(left, top);
}
```

That's quite a curious snippet. The function is called with only two variables as arguments, _offsetWidth_ and _offsetHeight_, and both are overwritten before use.

**Warning 3**

<a href="https://www.viva64.com/en/w/v6022/" target="_blank">V6022</a> Parameter 'shortcut' is not used inside constructor body. DeclarativeTrackingAction.java(47)

```java
public DeclarativeTrackingAction(String id, String caption, String description,
                                 String icon, String enable, String visible,
                                 String methodName, @Nullable String shortcut,
                                 ActionsHolder holder) {
  super(id);
  this.caption = caption;
  this.description = description;
  this.icon = icon;

  setEnabled(enable == null || Boolean.parseBoolean(enable));
  setVisible(visible == null || Boolean.parseBoolean(visible));

  this.methodName = methodName;
  checkActionsHolder(holder);
}
```

The function doesn't make use of the value passed as  the _shortcut_ parameter. Maybe the function's interface has become obsolete, or this warning is just a false positive.

A few more defects of this type:

* V6022 Parameter 'type' is not used inside constructor body. QueryNode.java(36)
* V6022 Parameter 'text2' is not used inside constructor body. MarkerAddition.java(22)
* V6022 Parameter 'selection' is not used inside constructor body. AceEditor.java(114)
* V6022 Parameter 'options' is not used inside constructor body. EntitySerialization.java(379)

Different functions, same code

**Warning 1**

<a href="https://www.viva64.com/en/w/v6032/" target="_blank">V6032</a> It is odd that the body of method 'firstItemId' is fully equivalent to the body of another method 'lastItemId'. ContainerTableItems.java(213), ContainerTableItems.java(219)

```java
@Override
public Object firstItemId() {
  List<E> items = container.getItems();
  return items.isEmpty() ? null : items.get(0).getId();
}

@Override
public Object lastItemId() {
  List<E> items = container.getItems();
  return items.isEmpty() ? null : items.get(0).getId();
}
```

The functions _firstItemId_ and _lastItemId_ have the same implementations. The latter was probably meant to get the index of the last element rather than get the element at index 0.

**Warning 2**

<a href="https://www.viva64.com/en/w/v6032/" target="_blank">V6032</a> It is odd that the body of method is fully equivalent to the body of another method. SearchComboBoxPainter.java(495), SearchComboBoxPainter.java(501)

```java
private void paintBackgroundDisabledAndEditable(Graphics2D g) {
  rect = decodeRect1();
  g.setPaint(color53);
  g.fill(rect);
}

private void paintBackgroundEnabledAndEditable(Graphics2D g) {
  rect = decodeRect1();
  g.setPaint(color53);
  g.fill(rect);
}
```

Two more functions with suspiciously identical bodies. My guess is that one of them was meant to work with some other color instead of _color53_.

### Null dereference

**Warning 1**

<a href="https://www.viva64.com/en/w/v6060/" target="_blank">V6060</a> The 'descriptionPopup' reference was utilized before it was verified against null. SuggestPopup.java(252), SuggestPopup.java(251)

```java
protected void updateDescriptionPopupPosition() {
  int x = getAbsoluteLeft() + WIDTH;
  int y = getAbsoluteTop();
  descriptionPopup.setPopupPosition(x, y);
  if (descriptionPopup!=null) {
    descriptionPopup.setPopupPosition(x, y);
  }
}
```

In just two lines, the programmer managed to write a highly suspicious piece of code. First the method _setPopupPosition_ of the object _descriptionPopup_ is called, and then the object is checked for _null_. The first call to _setPopupPosition_ is probably redundant and potentially dangerous. I guess it results from bad refactoring.

**Warning 2**

<a href="https://www.viva64.com/en/w/v6060/" target="_blank">V6060</a> The 'tableModel' reference was utilized before it was verified against null. DesktopAbstractTable.java(1580), DesktopAbstractTable.java(1564)

```java
protected Column addRuntimeGeneratedColumn(String columnId) {
  // store old cell editors / renderers
  TableCellEditor[] cellEditors =
    new TableCellEditor[tableModel.getColumnCount() + 1];         // <=
  TableCellRenderer[] cellRenderers =
    new TableCellRenderer[tableModel.getColumnCount() + 1];       // <=

  for (int i = 0; i < tableModel.getColumnCount(); i++) {         // <=
      Column tableModelColumn = tableModel.getColumn(i);

      if (tableModel.isGeneratedColumn(tableModelColumn)) {       // <=
          TableColumn tableColumn = getColumn(tableModelColumn);
          cellEditors[i] = tableColumn.getCellEditor();
          cellRenderers[i] = tableColumn.getCellRenderer();
      }
  }

  Column col = new Column(columnId, columnId);
  col.setEditable(false);

  columns.put(col.getId(), col);

  if (tableModel != null) {                                       // <=
      tableModel.addColumn(col);
  }
  ....
}
```

This case is similar to the previous one. By the time the _tableModel_ object is checked for _null_, it has already been accessed multiple times.

Another example:

* V6060 The 'tableModel' reference was utilized before it was verified against null. DesktopAbstractTable.java(596), DesktopAbstractTable.java(579)

### Probably a logic error

<a href="https://www.viva64.com/en/w/v6026/" target="_blank">V6026</a> This value is already assigned to the 'sortAscending' variable. CubaScrollTableWidget.java(488)

```java
@Override
protected void sortColumn() {
  ....
  if (sortAscending) {
    if (sortClickCounter < 2) {
      // special case for initial revert sorting instead of reset sort order
      if (sortClickCounter == 0) {
        client.updateVariable(paintableId, "sortascending", false, false);
      } else {
        reloadDataFromServer = false;
        sortClickCounter = 0;
        sortColumn = null;
        sortAscending = true;   // <=

        client.updateVariable(paintableId, "resetsortorder", "", true);
      }
    } else {
      client.updateVariable(paintableId, "sortascending", false, false);
    }
  } else {
    if (sortClickCounter < 2) {
      // special case for initial revert sorting instead of reset sort order
      if (sortClickCounter == 0) {
        client.updateVariable(paintableId, "sortascending", true, false);
      } else {
        reloadDataFromServer = false;
        sortClickCounter = 0;
        sortColumn = null;
        sortAscending = true;

        client.updateVariable(paintableId, "resetsortorder", "", true);
      }
    } else {
      reloadDataFromServer = false;
      sortClickCounter = 0;
      sortColumn = null;
      sortAscending = true;

      client.updateVariable(paintableId, "resetsortorder", "", true);
    }
  }
  ....
}
```

In the first condition, the variable _sortAscending_ has already been assigned the value _true_, but it's still assigned the same value again later on. This must be a mistake, and the author probably meant the value _false_.

A similar example from a different file:

* V6026 This value is already assigned to the 'sortAscending' variable. CubaTreeTableWidget.java(444)

### Strange return values

**Warning 1**

<a href="https://www.viva64.com/en/w/v6037/" target="_blank">V6037</a> An unconditional 'return' within a loop. QueryCacheManager.java(128)

```java
public <T> T getSingleResultFromCache(QueryKey queryKey, List<View> views) {
  ....
  for (Object id : queryResult.getResult()) {
    return (T) em.find(metaClass.getJavaClass(), id, views.toArray(....));
  }
  ....
}
```

The analyzer has detected an unconditional call to _return_ at the very first iteration of a _for_ loop. Either that line is incorrect or the loop should be rewritten as an _if_ statement.

**Warning 2**

<a href="https://www.viva64.com/en/w/v6014/" target="_blank">V6014</a> It's odd that this method always returns one and the same value. DefaultExceptionHandler.java(40)

```java
@Override
public boolean handle(ErrorEvent event, App app) {
  Throwable t = event.getThrowable();
  if (t instanceof SocketException
      || ExceptionUtils.getRootCause(t) instanceof SocketException) {
    return true;
  }
  if (ExceptionUtils.getThrowableList(t).stream()
      .anyMatch(o -> o.getClass().getName().equals("...."))) {
    return true;
  }
  if (StringUtils.contains(ExceptionUtils.getMessage(t), "....")) {
    return true;
  }
  AppUI ui = AppUI.getCurrent();
  if (ui == null) {
    return true;
  }
  if (t != null) {
    if (app.getConnection().getSession() != null) {
      showDialog(app, t);
    } else {
      showNotification(app, t);
    }
  }
  return true;
}
```

This function returns _true_ in each case, while the last line obviously calls for _false_. It looks like a mistake.

Here's a full list of other similar suspicious functions:

* V6014 It's odd that this method always returns one and the same value. ErrorNodesFinder.java(31)
* V6014 It's odd that this method always returns one and the same value. FileDownloadController.java(69)
* V6014 It's odd that this method always returns one and the same value. IdVarSelector.java(73)
* V6014 It's odd that this method always returns one and the same value. IdVarSelector.java(48)
* V6014 It's odd that this method always returns one and the same value. IdVarSelector.java(67)
* V6014 It's odd that this method always returns one and the same value. IdVarSelector.java(46)
* V6014 It's odd that this method always returns one and the same value. JoinVariableNode.java(57)

**Warning 3**

<a href="https://www.viva64.com/en/w/v6007/" target="_blank">V6007</a> Expression 'needReload' is always false. WebAbstractTable.java(2702)

```java

protected boolean handleSpecificVariables(Map<String, Object> variables) {
  boolean needReload = false;

  if (isUsePresentations() && presentations != null) {
    Presentations p = getPresentations();

    if (p.getCurrent() != null && p.isAutoSave(p.getCurrent())
        && needUpdatePresentation(variables)) {
      Element e = p.getSettings(p.getCurrent());
      saveSettings(e);
      p.setSettings(p.getCurrent(), e);
    }
  }
  return needReload;
}
```

The function returns the _needReload_ variable whose value is always _false_. Some code for changing that value is probably missing from one of the conditions.

**Warning 4**

<a href="https://www.viva64.com/en/w/v6062/" target="_blank">V6062</a> Possible infinite recursion inside the 'isFocused' method. GwtAceEditor.java(189), GwtAceEditor.java(190)

```java
public final native void focus() /*-{
  this.focus();
}-*/;

public final boolean isFocused() {
  return this.isFocused();
}
```

The analyzer has detected a recursive function with no stop condition. This file contains a lot of functions marked with the keyword _native_ and containing commented-out code. The developers are probably rewriting this file now and will soon notice the _isFocused_ function too. 

### Miscellaneous

**Warning 1**

<a href="https://www.viva64.com/en/w/v6002/" target="_blank">V6002</a> The switch statement does not cover all values of the 'Operation' enum: ADD. DesktopAbstractTable.java(665)

```java
/**
 * Operation which caused the datasource change.
 */
enum Operation {
    REFRESH,
    CLEAR,
    ADD,
    REMOVE,
    UPDATE
}

@Override
public void setDatasource(final CollectionDatasource datasource) {
  ....
  collectionChangeListener = e -> {
    switch (e.getOperation()) {
      case CLEAR:
      case REFRESH:
        fieldDatasources.clear();
        break;

      case UPDATE:
      case REMOVE:
        for (Object entity : e.getItems()) {
          fieldDatasources.remove(entity);
        }
        break;
    }
  };
  ....
}
```

The _switch_ statement has no case for the value _ADD_. It's the only value that's not being checked, so the developers should take a look at this code.

**Warning 2**

<a href="https://www.viva64.com/en/w/v6021/" target="_blank">V6021</a> Variable 'source' is not used. DefaultHorizontalLayoutDropHandler.java(177)

```java
@Override
protected void handleHTML5Drop(DragAndDropEvent event) {
  LayoutBoundTransferable transferable = (LayoutBoundTransferable) event
          .getTransferable();
  HorizontalLayoutTargetDetails details = (HorizontalLayoutTargetDetails) event
          .getTargetDetails();
  AbstractOrderedLayout layout = (AbstractOrderedLayout) details
          .getTarget();
  Component source = event.getTransferable().getSourceComponent(); // <=
  int idx = (details).getOverIndex();

  HorizontalDropLocation loc = (details).getDropLocation();
  if (loc == HorizontalDropLocation.CENTER
          || loc == HorizontalDropLocation.RIGHT) {
      idx++;
  }
  Component comp = resolveComponentFromHTML5Drop(event);
  if (idx >= 0) {
    layout.addComponent(comp, idx);
  } else {
    layout.addComponent(comp);
  }
  if (dropAlignment != null) {
    layout.setComponentAlignment(comp, dropAlignment);
  }
}
```

The variable _source_ is declared but not used.  Perhaps the authors forgot to add _source_ to _layout_, just like it happened with another variable of this type, _comp_.

Other functions with unused variables:

* V6021 Variable 'source' is not used. DefaultHorizontalLayoutDropHandler.java(175)
* V6021 The value is assigned to the 'r' variable but is not used. ExcelExporter.java(262)
* V6021 Variable 'over' is not used. DefaultCssLayoutDropHandler.java(49)
* V6021 Variable 'transferable' is not used. DefaultHorizontalLayoutDropHandler.java(171)
* V6021 Variable 'transferable' is not used. DefaultHorizontalLayoutDropHandler.java(169)
* V6021 Variable 'beanLocator' is not used. ScreenEventMixin.java(28)

**Warning 3**

<a href="https://www.viva64.com/en/w/v6054/" target="_blank">V6054</a> Classes should not be compared by their name. MessageTools.java(283)

```java
public boolean hasPropertyCaption(MetaProperty property) {
  Class<?> declaringClass = property.getDeclaringClass();
  if (declaringClass == null)
    return false;

  String caption = getPropertyCaption(property);
  int i = caption.indexOf('.');
  if (i > 0 && declaringClass.getSimpleName().equals(caption.substring(0, i)))
    return false;
  else
    return true;
}
```

The analyzer has detected a class comparison by name. It's incorrect to compare classes by name as, according to the specification, the names of JVM classes must be unique only within a package. Such a comparison yields incorrect results and leads to executing the wrong code.

<div class="citation"><div class="citation-line"></div><div class="citation-icon"></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Think Twice Before Using Reflection]]></title>
            <link>https://www.jmix.io/cuba-blog/think-twice-before-using-reflection</link>
            <guid>https://www.jmix.io/cuba-blog/think-twice-before-using-reflection</guid>
            <pubDate>Sun, 31 Mar 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/e6aead21cda74aaeb60a216f974248d3.png">In this article, we’ll look at reflection API, pros and cons for its usage and review other options to replace reflection API calls - AOT and code generation and LambdaMetafactory.]]></description>
            <content:encoded><![CDATA[### Introduction

Sometimes, as a developer, you may bump into a situation when it’s not possible to instantiate an object using the `new`<span id="_tmp_pre_1"></span> operator because its class name is stored somewhere in configuration XML or you need to invoke a method which name is specified as an annotation property. In such cases, you always have an answer: “Use reflection!”.

In the new version of <a href="http://cuba-platform.com" target="_blank">CUBA framework</a>, we decided to improve many aspects of the architecture and one of the most significant change was deprecating “classic“ event listeners in the controllers UI. In the previous version of the framework, a lot of boilerplate code registering listeners in screen's `init()` method made your code almost unreadable, so the new concept should have cleaned this up.


You can always implement method listener by storing `java.lang.reflect.Method` instances for annotated methods and invoke them like it is implemented in many frameworks, but we decided to have a look at other options. Reflection calls have their cost and if you develop a production-class framework, even tiny improvement may pay back in a short time.

In this article, we’ll look at reflection API, pros and cons for its usage and review other options to replace reflection API calls - AOT and code generation and LambdaMetafactory.

### Reflection - good old reliable API

"Reflection is the ability of a computer program to examine, introspect, and modify its own structure and behavior at runtime" according to Wikipedia.

For most Java developers reflection is not a new thing and it is used in many cases. I’d dare to say that Java won’t become what it is now without reflection. Just think about annotation processing, data serialization, method binding via annotations or configuration files… For the most popular IoC frameworks reflection API is a cornerstone because of extensive usage of class proxying, method reference usage, etc. Also, you can add aspect-oriented programming to this list - some AOP frameworks rely on reflection for method execution interception.

Are there any problems with reflection? We can think about three of them:

_Speed_ - reflection calls are slower than direct calls. We can see a great improvement in reflection API performance with every JVM release, JIT compiler’s optimization algorithms are getting better, but reflective method invocations are still about three times slower than direct ones.

_Type safety_ - if you use method reference in your code, it is just a method reference. If you write a code that invokes a method via its reference and passes wrong parameters, the invocation will fail at runtime, not at compile time or load-time.

_Traceability_ - if a reflective method call fails, it might be tricky to find a line of code that caused this, because stack trace is usually huge. You need to dig really deep into all these `invoke()` and `proxy()` calls.

But if you look into event listener implementations in Spring or JPA callbacks in Hibernate - you will see familiar `java.lang.reflect.Method` references inside. And I doubt that it will be changed in the nearest future - mature frameworks are big and complex, used in many mission-critical systems, so developers should introduce big changes carefully.

Let’s have a look at other options.

### AOT compilation and code generation - make applications fast again

The first candidate for reflection replacement - code generation. Nowadays we can see a rise of new frameworks like <a href="https://micronaut.io/" target="_blank">Micronaut</a> and <a href="https://quarkus.io/" target="_blank">Quarkus</a> that are targeted to two aims: fast start time and low memory footprint. Those two metrics are vital in the age of microservices and serverless applications. And recent frameworks are trying to get rid of reflection completely by using ahead-of-time compilation and code generation. By using annotation processing, type visitors and other techniques they add direct method calls, object instantiations, etc. into your code, therefore making applications faster. Those do not create and inject beans during startup using `Class.newInstance()`, do not use reflective method calls in listeners, etc. Looks very promising, but are there any trade-offs here? And the answer is - yes.

The first one - you run the code that is not yours exactly. Code generation changes your original code, therefore if something goes wrong you cannot tell whether it is your mistake or it is a glitch in the code processing algorithms. And don’t forget that now you should debug generated code, but not your code.

The second trade-off - you must use a separate tool/plugin provided by the vendor to use the framework. You cannot “just” run the code, you should pre-process it in a special way. And if you use the framework in production, you should apply the vendor’s bugfixes to both framework codebase and code processing tool.

Code generation has been known for a long time, it hasn’t appeared with <a href="https://micronaut.io/" target="_blank">Micronaut</a> or <a href="https://quarkus.io/" target="_blank">Quarkus</a>. For example, in <a href="https://cuba-platform.com" target="_blank">CUBA</a> we use class enhancement during compile-time using custom Grails plugin and <a href="http://www.javassist.org/" target="_blank">Javassist</a> library. We add extra code to generate entity update events and include bean validation messages to the class code as String fields for the nice UI representation.

But implementing code generation for event listeners looked a bit extreme because it would require a complete change of the internal architecture. Is there such a thing as reflection, but faster?

### LambdaMetafactory - faster method invocation

In Java 7, there was introduced a new JVM instruction - `invokedynamic`. Initially targeted at dynamic languages implementations based on JVM, it has become a good replacement for API calls. This API may give us a performance improvement over traditional reflection. And there are special classes to construct invokedynamic calls in your Java code:

*   `MethodHandle` - this class was introduced in Java 7, but it is still not well-known.

*   `LambdaMetafactory` - was introduced in Java 8\. It is further development of dynamic invocation idea. This API is based on MethodHandle.

Method handles API is a good replacement for standard reflection because JVM will perform all pre-invocation checks only once - during `MethodHandle` creation. Long story short - a method handle is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return values.

Surprisingly, pure MethodHandle reference invocation does not provide better performance comparing to reflection API unless you make MethodHandle references static as discussed in this <a href="http://mail.openjdk.java.net/pipermail/mlvm-dev/2018-February/006806.html" target="_blank">email list</a>.

But `LambdaMetafactory` is another story - it allows us to generate an instance of a functional interface in the runtime that contains a reference to a method resolved by `MethodHandle`. Using this lambda object, we can invoke the referenced method directly. Here is an example:

<pre><code>

private BiConsumer createVoidHandlerLambda(Object bean, Method method) throws Throwable {
        MethodHandles.Lookup caller = MethodHandles.lookup();
        CallSite site = LambdaMetafactory.metafactory(caller,
                "accept",
                MethodType.methodType(BiConsumer.class),
                MethodType.methodType(void.class, Object.class, Object.class),
                caller.findVirtual(bean.getClass(), method.getName(),
                        MethodType.methodType(void.class, method.getParameterTypes()[0])),
                MethodType.methodType(void.class, bean.getClass(), method.getParameterTypes()[0]));
        MethodHandle factory = site.getTarget();
        BiConsumer listenerMethod = (BiConsumer) factory.invoke();
        return listenerMethod;
    }
 </code>
</pre>

Please note that with this approach we can just use `java.util.function.BiConsumer` instead of `java.lang.reflect.Method`, therefore it won’t require too much refactoring. Let's consider event listener handler code - it is a simplified adaptation from Spring Framework:

<pre><code class="java">
public class ApplicationListenerMethodAdapter
        implements GenericApplicationListener {
    private final Method method;
    public void onApplicationEvent(ApplicationEvent event) {
        Object bean = getTargetBean();
        Object result = this.method.invoke(bean, event);
        handleResult(result);
    }
}
 </code>
</pre>

And that is how it can be changed with Lambda-based method reference:

```java
public class ApplicationListenerLambdaAdapter extends ApplicationListenerMethodAdapter {
    private final BiFunction funHandler;
    public void onApplicationEvent(ApplicationEvent event) {
        Object bean = getTargetBean();
        Object result = handler.apply(bean, event);
        handleResult(result);
    }
}
```

The code has subtle changes and functionality is the same. But it has some advantages over traditional reflection:

_Type safety_ - you specify method signature in `LambdaMetafactory.metafactory` call, therefore you won’t be able to bind “just” methods as event listeners.

_Traceability_ - lambda wrapper adds only one extra call to method invocation stack trace. It makes debugging much easier.

_Speed_ - this is a thing that should be measured.

#### Benchmarking

For the new version of CUBA framework, we created a JMH-based microbenchmark to compare execution time and throughput for “traditional” reflection method call, lambda-based one and we added direct method calls just for comparison. Both method references and lambdas were created and cached before test execution.

We used the following benchmark testing parameters:

```java
@BenchmarkMode({Mode.Throughput, Mode.AverageTime})
@Warmup(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
```

You can download the benchmark from <a href="https://github.com/cuba-rnd/entity-lambda-accessors-benchmark" target="_blank">GitHub</a> and run the test by yourself.

For JVM 11.0.2 and JMH 1.21 we got the following results (numbers may slightly vary from run to run):

<table width="100%">

<thead>

<tr>

<th>Test - Get Value</th>

<th>Throughput (ops/us)</th>

<th>Execution Time (us/op)</th>

</tr>

</thead>

<tbody>

<tr>

<td>LambdaGetTest</td>

<td>72</td>

<td>0.0118</td>

</tr>

<tr>

<td>ReflectionGetTest</td>

<td>65</td>

<td>0.0177</td>

</tr>

<tr>

<td>DirectMethodGetTest</td>

<td>260</td>

<td>0.0048</td>

</tr>

</tbody>

</table>

<table width="100%">

<thead>

<tr>

<th>Test - Set Value</th>

<th>Throughput (ops/us)</th>

<th>Execution Time (us/op)</th>

</tr>

</thead>

<tbody>

<tr>

<td>LambdaSetTest</td>

<td>96</td>

<td>0.0092</td>

</tr>

<tr>

<td>ReflectionSetTest</td>

<td>58</td>

<td>0.0173</td>

</tr>

<tr>

<td>DirectMethodSetTest</td>

<td>415</td>

<td>0.0031</td>

</tr>

</tbody>

</table>

As you can see, the lambda-based method handlers are about 30% faster on the average. There is a good discussion <a href="https://www.mail-archive.com/mlvm-dev@openjdk.java.net/msg06747.html" target="_blank">here</a> regarding lambda-based method invocation performance. The outcome - classes generated by LambdaMetafactory can be inlined, gaining some performance improvement. And it is faster than reflection because reflective calls had to pass security checks on every invocation.

This benchmark is pretty anemic and does not take into account class hierarchy, final methods, etc., it measures “just” method calls, but it was sufficient for our purpose.

### Implementation

In CUBA you can use `@Subscribe` annotation to make a method “listen” to various CUBA-specific application events. Internally we use this new MethodHandles/LambdaMetafactory based API for faster listener invocations. All the method handles are cached after the first invocation.

The new architecture has made the code cleaner and more manageable, especially in case of complex UI with a lot of event handlers. Just have a look at the simple example. Assume that you need to recalculate order amount based on products added to this order. You have a method `calculateAmount()` and you need to invoke it as soon as a collection of products in the order has changed. Here is the old version of the UI controller:

```java
public class OrderEdit extends AbstractEditor<Order> {
    @Inject
    private CollectionDatasource<OrderLine, UUID> linesDs;
    @Override
    public void init(
            Map<String, Object> params) {
        linesDs.addCollectionChangeListener(e -> calculateAmount());
    }
...
}
```

And here how it looks in the new version:

```java
public class OrderEdit extends StandardEditor<Order> {
    @Subscribe(id = "linesDc", target = Target.DATA_CONTAINER)
    protected void onOrderLinesDcCollectionChange (CollectionChangeEvent<OrderLine> event) {
            calculateAmount();
    }
...
}
```

The code is cleaner and we were able to get rid of the “magic” `init()`<span id="_tmp_pre_11"></span> method that is usually stuffed with event handler creation statements. And we don’t even need to inject data component into the controller - the framework will find it by the component ID.

### Conclusion

Despite the recent introduction of the new generation of the frameworks (<a href="https://micronaut.io" target="_blank">Micronaut</a>, <a href="https://quarkus.io" target="_blank">Quarkus</a>) that have some advantages over “traditional” frameworks, there is a huge amount of reflection-based code, thanks to <a href="https://spring.io" target="_blank">Spring</a>. We’ll see how the market will change in the nearest future, but nowadays Spring is the obvious leader among Java application frameworks, therefore we’ll be dealing with the reflection API for quite a long time.

And if you think about using reflection API in your code, whether you’re implementing your own framework or just an application, consider two other options - code generation and, especially, LambdaMetafactory. The latter will increase code execution speed, whilst development won’t take more time compared to “traditional” reflection API usage.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA 7: the New Chapter]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-7-the-new-chapter</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-7-the-new-chapter</guid>
            <pubDate>Mon, 04 Mar 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/996d9b9da96e4bcba88335456aade8ed.jpg">The word “major” in the upcoming releases of CUBA and Studio is well deserved. It is the most important release for the last 3 years, based on thorough analysis of the community feedback on the forum, conferences and Java User Groups. However, it comes with even more changes!]]></description>
            <content:encoded><![CDATA[The word “major” in the upcoming releases of CUBA and Studio is well deserved. It is the most important release for the last 3 years, based on thorough analysis of the community feedback on the forum, conferences and Java User Groups. However, it comes with even more changes!

### New API, features and stack upgrade

CUBA 7 introduces present-day concepts in software development: new event-based API, URL routing and visual components for Generic UI; a new way of data binding via lightweight data containers instead of hardly extensible datasources; underlying technology upgrade including Java 10+ support and a bunch of other improvements.

### CUBA Studio integrated into IntelliJ IDEA

Probably the biggest and the most awaited change! Now you don't need to switch between the Studio and IDE all the time - everything you need is always at hand, including Intuitive navigation, smart prompts, and code completion. This move also enables us to support not only Java and Groovy, but also other JVM languages, primarily Kotlin.

### Dashboards, Maps, and the New BPM

The Marketplace is growing rapidly with add-ons requested or contributed by the community, like LDAP, Data Import or WebDAV. Just recently we have published Dashboards, and in the upcoming months, we are looking forward to introducing the new BPM and Maps add-ons, which will be a major upgrade vs the existing ones.

### No more “10 entities limit”

We are making the licensing rules clearer. The limit of 10 entities for the Studio will be removed - meaning that you will be able to develop or migrate projects of any size for free. The commercial version of the Studio still remains. It focuses on extra development comfort with visual designers for entities, screens, menus, and other platform elements, while in the free version all this should be coded in the usual way.

### Premium Add-ons are going Open-Source

The licensing rules will be also changed towards the premium add-ons, which are currently bundled into the commercial subscription. Since the new CUBA Studio goes live, these add-ons will be separated from the commercial Studio subscription. So, for CUBA 7+ Reporting, BPM, FTS, and Charts will become free and open source!

To have a deeper look into changes read the official <a href="http://files.cuba-platform.com/cuba/release-notes/7.0/#premium_addons" target="_blank">release notes</a>.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's new in CUBA 7]]></title>
            <link>https://www.jmix.io/cuba-blog/whats-new-in-CUBA7</link>
            <guid>https://www.jmix.io/cuba-blog/whats-new-in-CUBA7</guid>
            <pubDate>Mon, 04 Mar 2019 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/81c73f41379d475a926d7ba9b65e3e65.jpg">Three years ago we announced the second publicly available major version of the framework. CUBA 6 was the game changing version - the licensing was turned from proprietary to Apache 2.0. Those days we couldn't even guess where it was going to bring the framework in long term.]]></description>
            <content:encoded><![CDATA[Three years ago we announced the second publicly available major version of the framework. [CUBA 6](https://www.cuba-platform.com/blog/whats-new-in-cuba-platform-6-0-and-studio-2-0) was the game changing version - the licensing was turned from proprietary to Apache 2.0\. Those days we couldn't even guess where it was going to bring the framework in long term. CUBA community started to grow exponentially, so we have learned a lot of possible (and sometimes impossible) ways of how developers use the framework. Now we are happy to announce CUBA 7, which, we hope, will make development more coherent and joyful for all community members from those just starting their journey in CUBA and Java to skilled enterprise developers and Java experts.

## Development Tools

Obviously, a great part of CUBA success we owe to [CUBA Studio](https://www.cuba-platform.com/development-tools). It has remarkably simplified the overwrought Java enterprise routine, in many places grounding it down to making trivial configurations in the visual designers: no need to know Persistence API or Gradle or even Spring to develop a complete and feature-rich CRUD application - Studio will do it for you.

![text]({{strapiUrl}}/uploads/cf6b68175cba407eb68c7553fb657149.png)

The Studio was a separate web application and this fact caused some significant limitations:

*   First of all, Studio was not a fully featured IDE, so developers had to switch between the Studio and IntelliJ IDEA or Eclipse to develop business logic and benefit from convenient navigation, code completion and other essential things, which was annoying.
*   Secondly, this magical simplicity was built over massive source code parsing and generation. Improving the code generation capabilities would mean moving towards development of a fully featured IDE - a too ambitious undertaking.

We decided to lean on another giant's shoulder to overcome these limitations. Studio was merged into IntelliJ IDEA by JetBrains. Now you can install it as a plugin for your IntelliJ IDEA or download as a separate standalone bundle.

![text]({{strapiUrl}}/uploads/f8cbab7f8080469398d9908d2a2adb9c.png)

This opens new horizons:

*   Other JVM languages support (and Kotlin in the first place)
*   Improved hot deploy
*   Intuitive navigation through the entire project
*   Smarter hints and code generators

Currently new Studio is under active development: we are porting features from the old version. The short term plan is also to re-implement web-based designers using native IntelliJ UI and improve project navigation experience.

## Stack Upgrade

Traditionally, the underlying stack has also been majorly upgraded, e.g. Java 8/11, Vaadin 8, Spring 5.

![text]({{strapiUrl}}/uploads/a3f52189a3af438cb05846af7cfbfea2.png)

By default new projects use Java 8, but you can specify the version of Java by adding the following clause to the build.gradle file:

```java
subprojects {
   sourceCompatibility = JavaVersion.VERSION_11
   targetCompatibility = JavaVersion.VERSION_11
}
```

Upgrade to Vaadin 8 was a big challenge because of massive breaking changes in the Vaadin data binding API. Fortunately, CUBA abstracts developers from Vaadin internals by wrapping it into its own API layer. CUBA team did a great job reimplementing internals keeping its own API untouched. This means that compatibility is fully saved and you can benefit from Vaadin 8 right after migrating a project to CUBA 7 without any refactoring.

The full list of updated dependencies is available in the official <a href="http://files.cuba-platform.com/cuba/release-notes/7.0/#upd_dep" target="_blank">release notes</a>.

## New Screens API

This section could also be named "The first screens API" - as CUBA has never had any officially declared API in the web client tier. It comes from the history of the framework and certain assumptions that were made at the first stage:

Declarative-centric approach - everything that can be described declaratively, should be declared in a screen descriptor and not coded in its controller

Standard screens (Browser and Editor) provide concrete generic functionality and there is no need to modify it

Since the first thousand members joined our community we realized how wide the variety of requirements for "standard" CRUD screens is - way beyond the initially-designed set of features. Nevertheless, for a long time, we were able to handle requests for custom behaviour even without an API layer - thanks to another first stage assumption - Open Inheritance. Effectively Open Inheritance means that you can override any public or protected method of an underlying class to tailor its behaviour to what you need. This might sound like a cure for all diseases, but in fact it doesn't give you even a short-term contract: what if the overridden method will be renamed, deleted or simply never used in the future versions of the framework?

![text]({{strapiUrl}}/uploads/00c471e4d5e34033898c2b51a42cbd42.png)

So, in response to the growing demand from the community we decided to introduce a new screens API. The API provides clear and long-term extension points with no hidden declarative magic, flexible and very easy to use.

### Screen Declaration

In CUBA 7 screen declaration is extremely simple:

```java
@UiController("new-screen") // screen id 
public class NewScreen extends Screen { }
```

From the example above we can see that screen identifier is explicitly defined right above the controller class. In other words, screen id and controller class now uniquely correspond to each other. So, good news, now screens can be addressed directly by their controller class in a safe way:

@Inject
private ScreenBuilders screenBuilders;
@Subscribe
private void onBeforeClose(BeforeCloseEvent event) {
   screenBuilders.screen(this)
           .withScreenClass(SomeConfirmationScreen.class)
           .build()
           .show();
}
</code></pre>

Screen descriptor becomes a complementary part instead of mandatory. The layout can be created programmatically or declared as an XML screen descriptor, which is defined by the @UiDescriptor annotation over the controller class. This makes controllers and layouting much easier to read and understand - this approach is very similar to the one used in Android development.

Before it was also required to register a screen descriptor in the web-screens.xml file and assign an identifier to it. In CUBA 7 this file is kept due to compatibility reasons, however, creating screens in a new way does not require such registration.

### Screens Lifecycle

The new API introduces clear and self-explanatory screen lifecycle events:

*   Init
*   AfterInit
*   BeforeShow
*   AfterShow
*   BeforeClose
*   AfterClose

All screen-related events in CUBA 7 can be subscribed as follows:

```java
@UiController("new-screen")
public class NewScreen extends Screen {
   
   @Subscribe
   private void onInit(InitEvent event) { 
   }
   
   @Subscribe
   private void onBeforeShow(BeforeShowEvent event) {      
   }

}
```
Comparing new API with the old approach you can see that we are not overriding hook-methods, which are obscurely called in the hierarchy of parent classes but define logic in clear predefined points of the screen lifecycle.

### Event Handling and Functional Delegates

In the previous section we learned how to subscribe to the lifecycle events, so, what about other components? Should we still scatter all required listeners on screen initialization as it was in 6.x versions? The new API is very uniform, so subscribing to other events is absolutely similar to the lifecycle ones.

Let's take a simple example with two UI elements: a button and a currency field, so its XML descriptor looks like:

```
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
       caption="msg://caption"
       messagesPack="com.company.demo.web">
   <layout>
       <hbox spacing="true">
           <currencyField id="currencyField" currency="$"
                          currencyLabelPosition="LEFT"/>
           <button id="calcPriceBtn" caption="Calculate Price"/>
       </hbox>
   </layout>
</window>
```

By clicking the button we call middleware service returning a number, which goes to the currency field. The currency field should change its style depending on the price value.

```
@UiController("demo_MyFirstScreen")
@UiDescriptor("my-first-screen.xml")
public class MyFirstScreen extends Screen {

   @Inject
   private PricingService pricingService;

   @Inject
   private CurrencyField<BigDecimal> currencyField;

   @Subscribe("calcPriceBtn")
   private void onCalcPriceBtnClick(Button.ClickEvent event) {
       currencyField.setValue(pricingService.calculatePrice());
   }

   @Subscribe("currencyField")
   private void onPriceChange(HasValue.ValueChangeEvent<BigDecimal> event) {
       BigDecimal price = pricingService.calculatePrice();
       currencyField.setStyleName(getStyleNameByPrice(price));
   }
  
   private String getStyleNameByPrice(BigDecimal price) {
       ...
   }
  
}
```

In the example above we can see two event handlers: one is invoked when the button is clicked and another one gets executed when the currency field changes its value - as simple as that.

Now, let's imagine that we need to validate our price and check that its value is positive. The straightforward way would be to add a validator while screen initialization:
```
@UiController("demo_MyFirstScreen")
@UiDescriptor("my-first-screen.xml")
public class MyFirstScreen extends Screen {

   @Inject
   private CurrencyField<BigDecimal> currencyField;

   @Subscribe
   private void onInit(InitEvent event) {
       currencyField.addValidator(value -> {
           if (value.compareTo(BigDecimal.ZERO) <= 0)
               throw new ValidationException("Price should be greater than zero");
       });
   }

}
```
In real world applications a screen entry point usually becomes littered with this kind of screen element initializers. To address this issue CUBA provides the useful annotation `@Install`. Let's see how it can help in our case:
```
@UiController("demo_MyFirstScreen")
@UiDescriptor("my-first-screen.xml")
public class MyFirstScreen extends Screen {

   @Inject
   private CurrencyField<BigDecimal> currencyField;

   @Install(to = "currencyField", subject = "validator")
   private void currencyFieldValidator(BigDecimal value) {
       if (value.compareTo(BigDecimal.ZERO) <= 0)
           throw new ValidationException("Price should be greater than zero");
   }
}
```
In fact, we delegate validation logic from our currency field to the _currencyFieldValidator_ method in our screen. This might look a bit complicated, however, developers adopt this feature surprisingly fast.

### Screen Builders / Notifications / Dialogs

![text]({{strapiUrl}}/uploads/2e7ca057d25c4a42915f3ac31e4b8d90.png)

CUBA 7 also introduces a set of useful components with fluent APIs:

*   **ScreenBuilders** combines fluent factories to generate standard lookups, editors and custom screens. The example below shows how you can open one screen from another. Note, that the _build()_ method returns the screen instance of the right type, without a need to unsafely cast it.
```
CurrencyConversions currencyConversions = screenBuilders.screen(this)
       .withScreenClass(CurrencyConversions.class)
       .withLaunchMode(OpenMode.DIALOG)
       .build();
currencyConversions.setBaseCurrency(Currency.EUR);
currencyConversions.show();
```
*   **Screens** component provides a lower level abstraction to creating and showing screens rather than _ScreenBuilders_. It also provides access to the information about all opened screens in your CUBA application (_Screens#getOpenedScreens_) in case if you need to iterate through them.
*   **Notifications** and **Dialogs** components both introduce convenient self-explanatory interfaces. Here is an example for creating and showing a dialog and a notification:
```
dialogs.createOptionDialog()
       .withCaption("My first dialog")
       .withMessage("Would you like to thank CUBA team?")
.withActions(
       new DialogAction(DialogAction.Type.YES).withHandler(e -> 
notifications.create()
               .withCaption("Thank you!")
               .withDescription("We appreciate all community members")
               .withPosition(Notifications.Position.MIDDLE_CENTER)
               .withHideDelayMs(3000)
               .show()),
       new DialogAction(DialogAction.Type.CANCEL)
)
       .show();
```
### Data Binding

CUBA enables extremely fast development of backoffice UIs not only by providing advanced visual tooling with extensive code-generation capabilities but also by a rich set of data-aware components available right out of the box. Such components just need to know what data they work with and the rest will be managed automatically, e.g. lookup lists, picker fields, various grids with CRUD operations and so on.

Before version 7 data binding was implemented via so-called datasources - objects that wrap a single entity or a collection of entities to reactively tie them with data-aware components. This approach worked very well, however, implementation-wise it was a monolith. The monolithic architecture typically causes problems with its customization, so in CUBA 7 this solid boulder was split into 3 data components:

*   **Data loader** is a data provider for data containers. Data loaders don't keep data, they just pass all required query parameters to a data store and feed data containers with the resulting data set.
*   **Data container** keeps the loaded data (a single entity or a number of entities) and provides it to the data-aware components in a reactive manner: all changes of the wrapped entities get exposed to the corresponding UI components and vice versa, all changes in the UI components will lead to the corresponding changes in its data container.
*   **Data context** is a powerful data modification manager that tracks changes and commits all modified entities. An entity can be merged into a data context, so it will provide a copy of the original entity with the only, but very important difference: all modifications of the resulting entity and all entities it references (including collections) will be tracked, stored and committed accordingly.

Data components can be declared in screen descriptors or instantiated programmatically using a specialized factory - _DataComponents_.

### Miscellaneous

Ufff, the most significant parts of the new screens API are described, so let me briefly list other important features in the web client tier:

*   **URL History and Navigation**. This feature solves a very common problem of SPA with “go back” button in a web browser, provides an easy way to assign routes to application screens and enables an API to reflect a current state of a screen in its URL.
*   **Form instead of FieldGroup.** <a href="https://doc.cuba-platform.com/manual-6.10/gui_FieldGroup.html" target="_blank">FieldGroup</a> is a data-aware component to show and modify fields of a single entity. It infers the actual UI shown for a field in runtime. In other words, if you have a Date field in your entity it will be shown as a <a href="https://doc.cuba-platform.com/manual-6.10/gui_DateField.html" target="_blank"><i>DateField</i></a>. However, if you would like to operate with this field programmatically, you will need to inject this field to the screen controller and cast it to the right type manually (_DateField_ in our example). Later on, we change our field type to some other and our application crashes at runtime… Form addresses this issue by explicit field type declaration. Find more information about this new component <a href="https://doc.cuba-platform.com/manual-7.0/gui_Form.html" target="_blank">here</a>.
*   **Third party** **JavaScript components integration** is significantly simplified, follow <a href="https://doc.cuba-platform.com/manual-7.0/jsComponent.html" target="_blank">the documentation</a> to embed custom JavaScript components into a CUBA application.
*   **HTML / CSS attributes** now can be easily defined right from the xml screen descriptor or set programmatically. Find more information <a href="https://doc.cuba-platform.com/manual-7.0/gui_attributes.html#gui_attr_css" target="_blank">here</a>.

## Middleware Features

The previous block about the new screens API was larger than I expected, so in this section, I'll try to be neat!

### Entity Changed Event

Entity Changed Event is a Spring application event that is fired when your entity made its way to a data store, got physically inserted and is within an inch of being committed. Here you can provide some additional checks (e.g. check product availability in stock before confirming an order) and modify it (e.g. recalculate totals) right before it will be visible for other transactions (of course with read committed isolation level). You can also use this event as the last chance to interrupt the transaction from being committed by throwing an exception - which might be useful in some corner cases.

There is also a way to catch the Entity Changed Event right after a commit has happened.

Follow <a href="https://doc.cuba-platform.com/manual-7.0/entityChangedEvent.html" target="_blank">this chapter</a> of the documentation to see an example.

### Transactional Data Manager

When developing an application we normally operate with detached entities - the ones which are not managed by any transaction. However, working with detached entities is not always possible, especially when trying to meet ACID requirements - this is the case when you can use the transactional data manager. It looks very similar to the ordinary data manager but differs in the following aspects:

*   It can join existing transaction (in case it is called under transactional context) or create its own transaction.
*   It has no _commit_ method, but there is the save method, which doesn't lead to immediate commit, but waits until the attached transaction will be committed.

Find an example of using it <a href="https://doc.cuba-platform.com/manual-7.0/transactionalDataManager.html" target="_blank">here</a>.

### JPA Lifecycle Callbacks

Finally, CUBA 7 supports JPA lifecycle callbacks. To not replicate well-written information about what these callbacks can be used for, let me just share <a href="https://docs.oracle.com/cd/E16439_01/doc.1013/e13981/undejbs003.htm#CIHCJGGJ" target="_blank">this link</a>, which fully covers the subject.

## What about Compatibility?

![text]({{strapiUrl}}/uploads/1d60cdcd31b2446dbcb5a890b436b146.png)

A fair question for any major release, especially when there are so many seemingly breaking changes! We have designed all these new features and APIs keeping in mind the backward compatibility:

*   The old screens API is supported in CUBA 7 and is implemented via the new one under the hood :)
*   We have also provided adapters for the old data binding, which keep working for the old fashioned screens.

So, good news, the migration path from version 6 to 7 should be quite straightforward.

## Conclusion

Concluding this technical overview I would like to mention that there are other important novations, especially with licensing:

*   The 10 entities limit for Studio is now gone
*   Reporting, BPM, Charts and Maps and Full text search addons are now free and  open source.
*   The commercial version of Studio brings extra development comfort with visual designers for entities, screens, menus, and other platform elements, while the free version focuses on working with code
*   Please note that for 6.x and older versions of the Platform and Studio licensing terms remain the same!

Finally, let me thank the community members again for all the support and feedback. I hope you will love version 7! The full list of changes are traditionally available in the <a href="http://files.cuba-platform.com/cuba/release-notes/7.0/" target="_blank">release notes</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Spring Query Interfaces in CUBA]]></title>
            <link>https://www.jmix.io/cuba-blog/spring-query-interfaces-in-cuba</link>
            <guid>https://www.jmix.io/cuba-blog/spring-query-interfaces-in-cuba</guid>
            <pubDate>Mon, 17 Dec 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/2729e0d9120142848eb185987a236597.png">Developers usually don’t like to change their coding habits. When I started working with <a href="https://www.cuba-platform.com/" target="_blank">CUBA</a>, I didn’t need to learn a lot of new things, creating applications was a pretty smooth process. One of the things that I ought to rediscover was working with data.
]]></description>
            <content:encoded><![CDATA[## Rationale

Developers usually don’t like to change their coding habits. When I started working with <a href="https://www.cuba-platform.com/" target="_blank">CUBA</a>, I didn’t need to learn a lot of new things, creating applications was a pretty smooth process. One of the things that I ought to rediscover was working with data.

In Spring there are several libraries that you can use for working with data, and one of the most popular is <a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html/" target="_blank">spring-data-jpa</a> which allows developers to avoid writing SQL or JPQL in most cases. You just need to specify an interface with methods that <a href="https://docs.spring.io/spring-data/data-commons/docs/current/reference/html/#repository-query-keywords" target="_blank">have special names</a> and Spring will generate and execute a query for you.

For example, this is an interface with a method to count all customers with a given last name:

```java
interface CustomerRepository extends CrudRepository<Customer, Long> {
  long countByLastName(String lastName);
}
```

You can inject this interface to your services and call this method where needed.

CUBA provides a lot of features out-of-the-box for data manipulation like partially loaded entities and sophisticated data security subsystem that restricts access to attributes or table rows. And all those features come with an API which is a bit different from well-known Spring Data or JPA/Hibernate.

So why don’t we have query interfaces in CUBA and is it possible to add them?

## Working with Data in CUBA

There are three main classes in CUBA’s API for working with data: DataStore, EntityManager, and DataManager.

<a href="https://doc.cuba-platform.com/manual-6.10/data_store.html" target="_blank">DataStore</a> abstraction provides an API to deal with a persistent storage like RDBMS, file system or cloud storage. It allows to perform basic operations with data, however, it is not recommended to work with DataStore directly unless you’re developing a custom persistent storage or in a need for very special access to the underlying storage.

<a href=" https://doc.cuba-platform.com/manual-6.10/entityManager.html" target="_blank">EntityManager</a> is mostly a copy of a well-known JPA EntityManager, but it has additional methods to work with <a href="https://doc.cuba-platform.com/manual-6.10/views.html" target="_blank">CUBA views</a>, soft deletion and methods to handle <a href="https://doc.cuba-platform.com/manual-6.10/query.html" target="_blank">CUBA queries</a>. As a CUBA developer you may rarely need this class in your day-to-day work, but in cases when you need to overcome CUBA’s security restrictions.

The next facility, <a href="https://doc.cuba-platform.com/manual-6.10/dataManager.html" target="_blank">DataManager</a>, is the main class to work with data in CUBA. It provides an API for data manipulation and <a href="https://doc.cuba-platform.com/manual-6.10/dm_security.html" target="_blank">supports CUBA security model</a> including attribute- and row-level security. When you select data, DataManager modifies it implicitly. For example, in case of a relational data store, it updates “select” clause to exclude restricted attributes and appends “where” condition(s) that filter out database rows that should not be visible to a current user. This security-awareness is just amazing, while development you don't need to remember what security filters should be applied in each query.

Here is a diagram of CUBA classes interaction for fetching data from an RDBMS when DataManager is used.

![text]({{strapiUrl}}/uploads/61c7c6c1494e4069bc80e59a2a1c60eb.png)

With DataManager you can select entities (as well as entity hierarchies using CUBA views) relatively easy. The simplest query may look like this:

`dataManager.load(Customer.class).list()`

DataManager will take care about filtering out “soft-deleted” records, restricted attributes and entities as well as creating a transaction.

But when it comes to queries with complex “where” conditions you need to write a JPQL statement.

For example, if you need to count all customers by their last name, you need to write something like this:

```java
public Long countByLastName(String lastName){
   return dataManager
           .loadValue("select count(c) from sample$Customer c where c.lastName = :lastName", Long.class)
           .parameter("lastName", lastName)
           .one();
}

public Long countByLastName(String lastName){
   LoadContext<Person> loadContext = LoadContext.create(Person.class);
   loadContext
      .setQueryString("select c from sample$Customer c where c.lastName = :lastName")
      .setParameter("lastName", lastName);
   return dataManager.getCount(loadContext);
}
```

As you can see, you need to pass JPQL statement to DataManager for execution. In CUBA API you should define JPQL as a string (Criteria API is not supported yet). It is a readable and clear definition of a query, but it might be a bit challenging to debug if something goes wrong. Also, JPQL strings cannot be verified by a compiler during application build or by Spring Framework during context initialization.

Compare it to Spring JPA code snippet:

```java
interface CustomerRepository extends CrudRepository<Customer, Long> {
  long countByLastName(String lastName);
}
```

It is three times shorter and does not include any strings. In addition to this, method _countByLastName_ is verified at deploy stage. If you make a typo in method’s name like _countByLastName_ there will be an error:

`Caused by: org.springframework.data.mapping.PropertyReferenceException: No property LastNome found for type Customer!`

Since CUBA is built over Spring framework you can add spring-data-jpa to CUBA project as a library and use this feature. The only issue - Spring’s query interfaces use JPA EntityManager under the hood, so queries will be processed neither by CUBA’s EntityManager nor by DataManager. Therefore, to add query interfaces to CUBA in a proper way they need to be customized - we need to replace all calls to EntityManager with DataManager’s methods invocations and add CUBA views support.

Some might argue that Spring approach is less manageable than CUBA’s because you do not have a control over query generation process. This is always a problem of a balance between convenience and a level of abstraction and it is up to a developer to choose which way to go. But it looks like having an additional (not the only one), simpler way to deal with data won’t hurt.

And if you need more control, in Spring there is <a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query" target="_blank">a way to specify your own query</a> for an interface method, so this option should and will be added to CUBA, too.

## Implementation

Query interfaces are implemented as a CUBA application module using <a href="https://docs.spring.io/spring-data/data-commons/docs/current/reference/html/" target="_blank">spring-data-commons</a>. This library contains classes for implementing custom query interfaces, for example, Spring’s <a href="https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/" target="_blank">spring-data-mongodb</a> library is based on it. Spring-data-commons utilizes proxying technique to create proper implementations of the declared query interfaces.

During CUBA’s context initialization all references to query interfaces are implicitly replaced by references to generated proxy beans published in the application context. When a developer invokes an interface method it is intercepted by a corresponding proxy. Then the proxy generates a JPQL query based on method’s name, substitutes parameters values and passes it to DataManager for execution. The diagram below shows simplified interaction between key components of the module.

![text]({{strapiUrl}}/uploads/37c3ae62375d4a9285581458b131ed5c.png)

## Using Query Interfaces in CUBA

To use CUBA query interfaces you need to add an application module in the project’s build file:

`appComponent("com.haulmont.addons.cuba.jpa.repositories:cuba-jpa-repositories-global:0.1-SNAPSHOT")`

XML configuration to enable query interfaces:

```java
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:context="http://www.springframework.org/schema/context"
            xmlns:repositories="http://www.cuba-platform.org/schema/data/jpa"
            xsi:schemaLocation="
   http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context-4.3.xsd
   http://www.cuba-platform.org/schema/data/jpa      
   http://www.cuba-platform.org/schema/data/jpa/cuba-repositories.xsd">

   <!-- Annotation-based beans -->
   <context:component-scan base-package="com.company.sample"/>

   <repositories:repositories base-package="com.company.sample.core.repositories"/>

</beans:beans>
```

If you prefer using annotations instead of creating XML config, you can enable query interfaces in the following way:

```java
@Configuration
@EnableCubaRepositories
public class AppConfig {
   //Configuration here
}
```

After enabling query interfaces you can create them in your application. An example of such an interface:

```java
public interface CustomerRepository extends CubaJpaRepository<Customer, UUID> {

   long countByLastName(String lastName);
   List<Customer> findByNameIsIn(List<String> names);

   @CubaView("_minimal")
   @JpqlQuery("select c from sample$Customer c where c.name like concat(:name, '%')")
   List<Customer> findByNameStartingWith(String name);
}
```

You can use _@CubaView_ and _@JpqlQuery_ annotations for query interface methods. The first one defines a <a href="https://doc.cuba-platform.com/manual-6.10/views.html" target="_blank">view</a> for the entities that will be fetched (“_local” is the default view if not specified). The second annotation specifies the exact JPQL query that will be used for this method if the query cannot be expressed <a href="https://docs.spring.io/spring-data/data-commons/docs/current/reference/html/#repository-query-keywords" target="_blank">with a method name</a>.

Query interfaces application component is attached to “global” CUBA module, so you can define and use query interfaces in both “core” and “web” modules, just don’t forget to enable them in the corresponding configuration files. The interface usage example is below:

```java
@Service(CustomerService.NAME)
public class CustomerServiceBean implements PersonService {

   @Inject
   private CustomerRepository customerRepository;

   @Override
   public List<Date> getCustomersBirthDatesByLastName(String name) {
      return customerRepository.findByNameStartingWith(name)
            .stream().map(Customer::getBirthDate).collect(Collectors.toList());
   }
}
```


## Conclusion

CUBA is flexible. If you feel that you need an additional feature for all your application and you don’t want to wait for the new version of CUBA, it is pretty easy to implement and add it not touching CUBA core. By adding query Interfaces to CUBA we hope to help developers work more efficiently delivering reliable code faster. The first version of the library is available at <a href="https://github.com/cuba-rnd/cuba-jpa-repositories" target="_blank">GitHub</a> and supports CUBA version 6.10 and higher.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[J2CL - Better late than never]]></title>
            <link>https://www.jmix.io/cuba-blog/j2cl-better-late-than-never</link>
            <guid>https://www.jmix.io/cuba-blog/j2cl-better-late-than-never</guid>
            <pubDate>Mon, 10 Dec 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/53d3c338f4984208842acf1107bea7f2.jpg">Last week the Google team has finally <a href="https://github.com/google/j2cl" target="_blank">published the source code of J2CL framework</a>, which has been discussed since 2015\. The idea of translating Java to JavaScript is not new at all, and everyone has had a hard time with Google Web Toolkit long before, yet this product was on the watch of the community like no other - it was discussed and became the topic of talks on conferences, but **nobody’s seen it**.
]]></description>
            <content:encoded><![CDATA[**No one has ever been late to their own funeral.**

Valentine Domil

Last week the Google team has finally <a href="https://github.com/google/j2cl" target="_blank">published the source code of J2CL framework</a>, which has been discussed since 2015\. The idea of translating Java to JavaScript is not new at all, and everyone has had a hard time with Google Web Toolkit long before, yet this product was on the watch of the community like no other - it was discussed and became the topic of talks on conferences, but **nobody’s seen it**.

It’s been more than 3 years since the first announcement and it seems that the product lost its market even before its birth. Today we have Scala.js, Kotlin.js, and JSweet, and, besides, the development is already occupied by TypeScript and there’s no place for Java anymore. For such a long time even most devoted Java guys have lost their faith in “Java for Front end” and learned some JavaScript framework.

But since it is finally released, let’s have a look at the result and for what purposes it can be used.

## Idea

Globally, emulating JVM in a browser is rather a complicated task. Google Web Toolkit developers have been trying to solve this problem for a long time and have achieved certain success: they built up a transpiler, developed standard Java library emulation mechanisms, provided the tooling for applications development.

Such an approach has many advantages: static type checking, reusability of a server code in a browser, ready-made tools represented by Java IDE. Many built-in approaches of GWT are now represented in TypeScript, Web Pack and other front-end development tools.

Good old Google Web Toolkit was taken against for being cumbersome and an abstract way of UI building. The idea of J2CL is simpler - it lets us translate Java to JavaScript with least possible overhead so that you could easily call Java from JavaScript and vice versa.

And even if in far 2015 there was a really good transpiler from Java to JS which would operate with no hash, it is nearly impossible to assume how would the web-development evolve then.

## J2CL Prequel

At the beginning of 2015 Google GWT team took a hard, but urgent decision - to develop a new product enabling Java for front-end development.

Mainly it was due to the changes in the web-development trends and their new internal customers who considered Java for web not as an isolated ecosystem, but as an essential part of a large stack. It required a completely innovative point of view and creating the tools which should be closely integrated into the rest ecosystem from scratch.

With GWT it was almost impossible to achieve such aims. And though GWT had means of two-way interaction with JavaScipt, the framework couldn’t get rid of the great burden of UI, RPC library and other applied API.

## What is that beast

As <a href="https://github.com/google/j2cl" target="_blank">the developers claim</a>, J2CL makes a seamless integration of Java code into JavaScript applications. It represents a simple and lightweight Java-to-JavaScript transpiler focused on the code optimization with the help of <a href="https://github.com/google/closure-compiler" target="_blank">Closure Compiler</a>.

*   It’s easy to mix Java and JavaScript in one project, getting the best of each language.
*   It lets reuse the code between the server solution, web-app and Android platform. Many Java libraries are available such as Guava, Dagger and AutoValue.
*   Modern and handy. The project build system is based on <a href="https://bazel.build/" target="_blank">Bazel</a>, Live-reload is supported.
*   Battle-proven. It’s claimed that J2CL is used in GSuite projects production: Gmail, Docs, Slides and Calendar.

In fact, J2CL translates source Java code to JavaScript code without Java classes bytecode. It means that, as it is in the case of Google Web Toolkit, all the used libraries sources are required for the project compilation. Besides, it raises the question of Java language capabilities supported in the latest releases. At this stage, the developers promise support of all syntax features of Java 11.

J2CL won’t support GWT Widgets, GWT RPC and other GWT libraries - only the basic Java and JavaScript integration tool - <a href="http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJsInterop.html" target="_blank">JSInterop</a>.

I.e. this is quite a limited GWT version with a completely new transpiler. And since the new product is no longer compatible with GWT, it is called J2CL instead of GWT. On the whole, the upcoming GWT 3 release will represent a framework over J2CL where all the applicable libraries will be separated from the translator system level.

Existing Java compatibility constraints are described <a href="https://github.com/google/j2cl/blob/master/docs/limitations.md" target="_blank">on GitHub</a>. They are mainly the same as in GWT - there’s no reflection support, no network Java API. But there’s also something different - array and list semantics are not emulated, for example, checking if an index is within the array is not executed. The developers put highlight not on the JVM behavior emulation, but on the syntax means of language to minimize the overhead costs and avoid generating tons of JavaScript to ensure full compatibility.

Although J2CL is ready for production, its OSS version is far from it. For example, there are some  <a href="https://github.com/google/j2cl/issues/9" target="_blank">on problems with project start on Windows</a>, and the developers can’t guarantee a stable API.

The choice of Bazel as a build system for an internal Google product is fair enough, but there are no advantages for the community in it and there’s no other way to use J2CL but to learn this build system. Meanwhile, we can only wait for the community to make plugins for Maven / Gradle.

## Starting to work

First, J2CL requires Mac OS or Linux.

Second, you have to install <a href="https://docs.bazel.build/versions/master/install.html" target="_blank">Bazel</a> - rather an exotic build system made by Google.

Now you can build some things, for example, HelloWorld from the <a href="https://github.com/google/j2cl/tree/master/samples/helloworld" target="_blank">official repository</a>.

`> bazel build src/main/java/com/google/j2cl/samples/helloworld:helloworld`

When you look at the output, you’ll be pleasantly surprised:

`> cat bazel-bin/src/main/java/com/google/j2cl/samples/helloworld/helloworld.js  
document.write('Hello from Java! and JS!');`

Surely, it doesn’t prove anything, but it’s great to see such a minimalism after all GWT modules. There are no other application examples, so we’ll wait until they show up.

## What it is for if we have xxx.js

For now, it is hard to tell what it is for. At first sight, J2CL comprises quite a bold idea - to reuse Java for front-end in the same way as TypeScript. On the other hand, the project seems to miss the boat.

New JS transpiler projects such as Kotlin.js and Scala.js are implemented as plugins for compilers and don’t require the source code parsing. From this point of view, J2CL is a step backward as it requires the sources to analyze.

One more questionable point is Java itself. Why use verbose Java when you can write both server and client side on laconic Kotlin?

However, comparing with another similar project - <a href="https://github.com/cincheo/jsweet" target="_blank">JSweet</a>, I trust J2CL more. JSweet tooling is much friendlier and more usable, but JSweet community is rather small and it is almost entirely written by a single person.

## So you say it’s open source?

It is definitely good news that the project is under Apache 2.0 free license.

Unfortunately, _open source code_ is not the same as the _open development process_. The community’s <a href="https://groups.google.com/forum/#!topic/Google-Web-Toolkit-Contributors/9Zi4-C5gpxQ" target="_blank">greatest disappointment</a> emerged because of the current situation, J2CL project was announced 3 years ago, but no one has shown its source code, you can’t influence its final API or speed up the development process because there’s nowhere to send hotfixes.

Let’s hope the situation will change for the best and the product will go live.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[In any incomprehensible situation go scripting]]></title>
            <link>https://www.jmix.io/cuba-blog/in-any-incomprehensible-situation-go-scripting</link>
            <guid>https://www.jmix.io/cuba-blog/in-any-incomprehensible-situation-go-scripting</guid>
            <pubDate>Tue, 20 Nov 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/94cb049236ce4a89a3491ce0fd6006cf.jpg">Scripting is one of the most popular ways to make your application adjustable for client needs right at runtime. As always, this approach brings not only good, e.g. there is a well-known trade-off between flexibility and manageability. ]]></description>
            <content:encoded><![CDATA[Scripting is one of the most popular ways to make your application adjustable for client needs right at runtime. As always, this approach brings not only good, e.g. there is a well-known trade-off between flexibility and manageability. This article is not one of those which theoretically discuss pros and cons, it practically shows different ways of how to adopt scripting and introduces a Spring library that provides convenient scripting infrastructure and useful features.

## Introduction

Scripting (aka plugin architecture) is the most straightforward way to make your application customizable in runtime. Quite often, scripting comes into your application not by design, but accidentally. Say, you have a very unclear part in a functional specification, so not to waste one another day for additional business analysis we decide to create an extension point and call a script that implements a stub - will clarify how it should work later.

There are a lot of well-known pros and cons of using such approach: e.g. great flexibility to define business logic in runtime and saving a massive amount of time on redeployment versus impossibility to perform comprehensive testing, hence, unpredictable problems with security, performance issues and so on.

The ways of doing scripting discussed further might be helpful both for the ones who already decided to stick with scripting plugins in their Java application or just thinking about adding it to their code.

## Nothing Special, Just Scripting

With Java’s JSR-233 API evaluating scripts in Java is a simple task. There is a number of production-class evaluating engines implemented for this API (Nashorn, JRuby, Jython, etc.), so it is not a problem to add some scripting magic to java code like shown here:

```java
   Map parameters = createParametersMap();
   ScriptEngineManager manager = new ScriptEngineManager();
   ScriptEngine scriptEngine = manager.getEngineByName("groovy");
   Object result = scriptEngine.eval(script.getScriptAsString("discount.groovy"), 
                                new SimpleBindings(parameters));
```

Obviously, having such code scattered over all your application is not a great idea when you have more than one script file and one invocation in your codebase, so you may extract this snippet into a separate method placed to utility class. Sometimes you might go even a bit further: you can create a special class (or set of classes) that group scripted business logic based on a business domain, e.g. class _PricingScriptService_. This will let us wrap calls to _evaluateGroovy()_ into a nice strongly typed methods, but there is still some boilerplate code, all methods will contain parameter mapping, script text loading logic and script evaluation engine invocation similar to this:

```java
public BigDecimal applyCustomerDiscount(Customer customer, BigDecimal orderAmount) {
  Map params = new HashMap&lt;&gt;();
  params.put("cust", customer);
  params.put("amount", orderAmount);
  return (BigDecimal)scripting.evalGroovy(getScriptSrc("discount.groovy"), params);
}
```

This approach brings more transparency in terms of knowing parameter types and return value type. And do not forget to add a rule prohibiting “unwrapped” scripting engine calls into your coding standards document!

## Scripting On Steroids

Despite the fact that using scripting engines is quite simple, if you have a lot of scripts in your codebase, you may encounter some performance problems. As an example - you use groovy templates for reporting and run a lot of reports at the same time. Sooner or later you’ll see that “simple” scripting is becoming a performance bottleneck.

That’s why some frameworks build their own scripting engine over existing API, adding some nice features for better performance, execution monitoring, polyglot scripting, etc.

For example, in CUBA framework there is a pretty sophisticated <a href="https://doc.cuba-platform.com/manual-6.10/scripting.html" target="_blank">Scripting</a> engine that implements features to improve script implementation and execution such as:

1.  Class cache to avoid repetitive script compilation.
2.  Ability to write scripts using both Groovy and Java languages.
3.  JMX bean for scripting engine management.

All of these improve performance and usability, but still, those are low-level APIs for creating parameter maps, fetching script text, etc., therefore we still need to group them into high order modules to use scripting efficiently in an application.

And it would be unfair not to mention new experimental GraalVM engine and its polyglot API that allows us to <a href="https://medium.com/p/12d9111f307d#2115" target="_blank">extend Java applications</a> with other languages. So maybe we will see Nashorn retired sooner or later and be able to write on different programming languages in the same source file, but it’s in the future still.

## Spring Framework: Offer That is Hard to Refuse?

In Spring Framework we have a built-in scripting support over the JDK’s API, you can find a lot of useful classes in org.springframework.scripting.* packages. There are evaluators, factories, etc. all the tools you need to build your own scripting support.

Aside from low-level APIs, Spring Framework has an implementation that should simplify dealing with scripts in your application - you can define beans implemented in dynamic languages as described in <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/languages.html#dynamic-language-beans" target="_blank">documentation</a>.

All you need to do is to implement a class using a dynamic language like Groovy and describe a bean in configuration XML like this:

```java
<lang:groovy id="messenger" script-source="classpath:Messenger.groovy">
        <lang:property name="message" value="I Can Do The Frug" />
</lang:groovy>
```

After that, you can inject Messenger bean into your application classes using XML config. That bean can be “refreshed” automatically in case of underlying script changes, be advised with AOP, etc.

This approach looks good, but you as a developer should implement full-fledged classes for your beans if you want to utilize all the power of dynamic language support. In real life scripts may be pure functions, therefore you need to add some extra code to your script just to keep it compatible with Spring. Also nowadays some developers think of an XML configuration as of “outdated” comparing to annotations and try to avoid using it, because bean definitions and injections are split between Java code and XML code. Though it is more a matter of taste rather than performance/compatibility/readability etc., we might take it into account.

## Scripting: Challenges and Ideas

So, everything has its price and when you add scripting to your application you may meet some challenges:

1.  Manageability - Usually scripts are scattered along the application, so it is quite hard to manage numerous _evaluateGroovy_ (or similar) calls.
2.  Discoverability - if something goes wrong in a calling script it's quite hard to find the actual point in the source code. We should be able to find all script invocation points easily in our IDE.
3.  Transparency - writing a scripted extension is not a trivial thing, as there is no information about variables sent to the script and also there is no information about the result it should return. In the end, scripting can be only done by a developer and only looking into the sources.
4.  Test and Updates - deploying (updating) a new script is always dangerous, there is no way to rollback and no tooling to test it before production.

It seems like hiding scripted method calls under regular Java methods may resolve most of these challenges. Preferable way - inject “scripted” beans and call their methods with meaningful names rather than to invoke just another “eval” method from utility class. Therefore our code is becoming self-documented, a developer won’t need to look into file “disc_10_cl.groovy” to figure out parameter names, types, etc.

One more advantage - if all scripts have unique java methods associated with them, it will be easy to find all extension points in the application using “Find Usages” feature in IDE as well as to understand what are the parameters for this script and what it returns.

This way of doing scripting also makes testing simpler - we’ll be able not only to test these classes “as usual”, but also use mocking frameworks if needed.

All of this reminds of the approach mentioned at the beginning of this article - “special” classes for scripted methods. And what if we will go one step further and hide all the calls to a scripting engine, parameter creation etc. from a developer?

## Scripting Repository Concept

The idea is pretty simple and should be familiar to all developers who worked with Spring Framework. We just create a java interface and link its methods to scripts somehow. As an example, Spring Data JPA uses a similar approach, where interface methods are transformed to SQL queries based on method’s name and then executed by an ORM engine.

What we may need to implement the concept?

Probably a class level annotation that will help us to detect script repository interfaces and construct a special Spring bean for them.

Method level annotation will help us to link the method to its scripted implementation.

And it would be nice to have a default implementation for the method that is not a simple stub, but a valid part of the business logic. It will work until we implement an algorithm developed by a business analyst. Or we can let him/her write this script :-)

Assume that you need to create a service to calculate a discount based on a user’s profile. And the business analyst says that we can safely assume that a 10% discount can be provided for all registered customers by default. We may think about the following code concept for this case:

```java
@ScriptRepository
public interface PricingRepository {

       @ScriptMethod
           default BigDecimal applyCustomerDiscount(Customer customer,
                         BigDecimal orderAmount) {
             return orderAmount.multiply(new BigDecimal("0.9"));
       }
}
```

And when it comes to proper discounting algorithm implementation the groovy script will be like this:

```java
-------- file discount.groovy --------
def age = 50
if ((Calendar.YEAR - cust.birthday.year) &gt;= age) {
   return amount.multiply(0.75)
}
--------
```

An ultimate goal for all this - let a developer implement an only interface and the discounting algorithm script only, and do not fumble with all those “getEngine” and “eval” calls. Scripting solution should do all the magic: when the method is invoked, intercept the invocation, find and load the script text, evaluate it and return the result (or execute default method if the script text is not found). The ideal usage should look similar to this:

```java
@Service
public class CustomerServiceBean implements CustomerService {

   @Inject
   private PricingRepository pricingRepository;

   //Other injected beans here

   @Override
   public BigDecimal applyCustomerDiscount(Customer cust, BigDecimal orderAmnt) {
   if (customer.isRegistered()) {
       return pricingRepository.applyCustomerDiscount(cust, orderAmnt);
   } else {
       return orderAmnt;
   }

   //Other service methods here

 }
```

The script call is readable and the way it is invoked is familiar to any java developer I guess.

Those were the ideas and they were used to create a library for script repositories implementation using Spring Framework. The library has facilities for script text load from different sources and evaluation as well as some APIs that allow a developer to implement extensions for the library if needed.

## How It Works

The library introduces some annotations (as well as XML config for those who prefer it) that initiate dynamic proxies construction for all repository interfaces marked with _@ScriptRepository_ annotation during its context initialization. Those proxies are published as singleton beans that implement repository interfaces meaning that you can inject those proxies into your beans using _@Autowired_ or _@Inject_ exactly as shown in the code snippet in the previous section.

_@EnableScriptRepositories_ annotation used on one of the application configuration classes activates script repositories. This approach is similar to other familiar Spring annotations like _@EnableJpaRepositories_ or @EnableMongoRepositories. And for this annotation you need to specify the array of package names that should be scanned similarly to JPA repositories.

```java
@Configuration
@EnableScriptRepositories(basePackages = {"com.example", "com.sample"})
public class CoreConfig {
//More configuration here.
}
```

As it was shown before, we need to mark every method in script repository with _@ScriptMethod_ (library provides _@GroovyScript_ and _@JavaScript_ as well), to add metadata to those calls and indicate that these methods are scripted. And default implementation for scripted methods is supported, of course. All components of the solution are displayed in the diagram below. Blue shapes are related to application code, white ones - to the library. Spring beans are marked with a Spring logo.

![text]({{strapiUrl}}/uploads/b79499cd76f74c389faa25d74650e58a.png)

When an interface’s scripted method is called it is intercepted by a proxy class, which performs a lookup for two beans - a provider to get implementing script text and an evaluator to get the result. After script evaluation the result is returned to a calling service. Both provider and evaluator may be specified in _@ScriptMethod_ annotation properties as well as execution timeout (library provides default values for these properties, though):

```java
@ScriptRepository
public interface PricingRepository {

@ScriptMethod (providerBeanName = "resourceProvider",
               evaluatorBeanName = "groovyEvaluator",
  timeout = 100)
default BigDecimal applyCustomerDiscount(
       @ScriptParam("cust") Customer customer,
       @ScriptParam("amount") BigDecimal orderAmount) {
   return orderAmount.multiply(new BigDecimal("0.9"));
}
}
```

You may notice _@ScriptParam_ annotation - we need them to provide names for method’s parameters. Those names should be used in the script since Java compiler erases actual parameter names on compilation. You can omit those annotations, in this case you’ll need to name script’s parameters “arg0”, “arg1”, etc. which affects code readability.

By default, the library has providers which can read groovy and javascript files from the file system and JSR-233 based evaluators for both script languages. You can create custom providers and evaluators for different script stores and execution engines though. All these facilities are based on Spring framework interfaces (_org.springframework.scripting.ScriptSource_ and _org.springframework.scripting.ScriptEvaluator_), so you can reuse all your Spring-based classes, e.g. _StandardScriptEvaluator_ instead of the default one.

Providers (as well as evaluators) are published as Spring beans because script repository proxy resolves them by name for the sake of flexibility - you can substitute default executor with a new one without changing application code, but replacing one bean in the application context.

## Testing and Versioning

Since scripts may be changed easily, we need to ensure that we won’t break the production server when we change a script. The library is compatible with JUnit test framework, there is nothing special about it. Since you use it in a Spring-based application, you can test your scripts using both unit tests and integration tests as a part of the application before uploading them to production, mocking is also supported.

In addition, you can create a script provider that reads different script text versions from a database or even from Git or another source control system. In this case it will be easy to switch to a newer script version or to roll back to the previous version of a script if something goes wrong in production.

## Conclusion

The library will help you to arrange scripts in your code providing the following:

1.  By introducing java interfaces, a developer always has an information about script parameters and their types.
2.  Providers and evaluators help you to get rid of scripting engine calls scattered through your application code.
3.  We can easily locate all script usages in the application code by using “Find usages (references)” IDE command or just simple text search by method name.

On top of this Spring Boot autoconfiguration is supported, and you also can test your scripts before deploying them to production using familiar unit tests and mocking technique.

The library has an API for getting scripts metadata (method names, parameters, etc.) in runtime, you can get wrapped execution results if you want to avoid writing try..catch blocks to deal with exceptions thrown by scripts, also it supports XML configuration if you prefer to store your config in this format.

Also, script execution time can be limited with a timeout parameter in an annotation.

Library sources can be found at <a href="https://github.com/cuba-rnd/spring-script-repositories" target="_blank">https://github.com/cuba-rnd/spring-script-repositories</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Off the Rails: getting RADical with CUBA]]></title>
            <link>https://www.jmix.io/cuba-blog/off-the-rails</link>
            <guid>https://www.jmix.io/cuba-blog/off-the-rails</guid>
            <pubDate>Fri, 09 Nov 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/2b0f2d994aaf415bb486d06f39baabe3.png">In the developer's life it happens to change one framework to another. The article is exactly about this, it shows the impressions of an experienced RoR developer moving to CUBA Platform. What is similar and what is perpendicular, what is more productive and what is easier to understand - read more in the article!]]></description>
            <content:encoded><![CDATA[In the developer's life it happens to change one framework to another. The article is exactly about this, it shows the impressions of an experienced RoR developer moving to CUBA Platform. What is similar and what is perpendicular, what is more productive and what is easier to understand - read more in the article!

<div class="citation"><div class="citation-line"></div><div class="citation-icon"></div></div>

Herby Raynaud, original post is <a href="https://www.yieldmo.com/dev_blog/off-the-rails-getting-radical-with-cuba/" target="_blank">here</a>

Having spent the past 6 years or so working on Rails apps, I was both intrigued and somewhat terrified when I learned that in my new job I’d be coding mostly in Java and in particular using a little known application framework called CUBA. I worked as a Java developer several years ago at a previous job, so I was familiar enough with Java and quite liked it as a programming language. However, I always felt overwhelmed and bewildered by the pot-pourri of enterprise-y (and often convoluted) technologies such as EJB, J2EE, JMS, JMX, Struts, AWT, Swing, JSF, Spring, etc., that one had to know in order to be considered a competent Java developer or even to build a simple web app.

Later, when I discovered Ruby and <a href="https://rubyonrails.org/" target="_blank">Ruby on Rails</a>, I felt like I was Dorothy stepping out of a bleak and barren Kansas landscape into the dazzling garden wonderland of Oz. It’s not hard to see why, when you consider that even as newbie Ruby developer I could create functional web application with Rails, literally in minutes, by simply executing the following eight command lines at a terminal.

![text]({{strapiUrl}}/uploads/0573516c90d54a4182ed4d728e1bcac7.png)

Granted, this fictional sales app we just created above is pretty basic, the mere fact that I could get this far so easily did indeed seem like the work of a wizard. Frameworks such as <a href="https://grails.org/" target="_blank">Grails</a> and <a href="https://www.playframework.com/" target="_blank">Play</a>, which are heavily influenced by Ruby on Rails, bring similar features to JVM languages.

It’s not easy to make true apples to apples comparison between CUBA and Rails (or Grails and Play for that matter) so I will limit the rest of this discussion to the area where these frameworks and specifically Rails overlap – namely rapidly building CRUD business applications.

Returning to the sales application we created above, here is where we are after all the commands have completed. There is a customer model with two string fields: name and email. There is an order model with an amount field and a foreign key reference to the customer model. There are database migration scripts that will create the customers and orders tables in the DB as well as RESTful routes to the customers and orders resources. Finally, the `generate scaffold` command also generated basic CRUD templates for both customers and orders.

CUBA, as a self described “Java RAD framework for enterprise web applications” (note the scary E word), takes a different approach altogether to building applications. For starters, to be as productive as possible in CUBA, it’s a good idea to download and run a separate application called CUBA Studio. Though not required, it automates a lot of tasks like generating Java and XML boilerplate and updating spring and gradle config files. More importantly it includes the drag and drop GUI builder. Once Studio is up and running the steps to building an app are roughly the same:

1.  Create a new project
2.  Create the Customers entity
3.  Create the Orders entity
4.  Generate the database and tables
5.  Generate the Customers UI screens
6.  Generate the Orders UI screens
7.  Compile the Sales application
8.  Start the application
9.  Navigate to localhost:8080 in your browser

The big difference of course is that you’re interacting with the Studio UI to accomplish these tasks. Also, in the interest of keeping this post short, I’ve glossed over a handful of intermediate steps in the CUBA workflow such as adding fields to the customers and orders entities (models) and setting up associations between the two.

I’ve attached a couple of short videos from the CUBA core team that show the actual process of building the Sales app in detail.

Overall, the CUBA workflow requires more of a hands-on-keyboard approach at each step of the application setup, which makes it less efficient than the command line approach provided by Rails and other frameworks. Still, the process is fairly painless and, as we’ll see in a bit, the additional out-of-the-box features provided by CUBA more than compensate for the added overhead.

Going back once again to our Rails app, we see that it is functional but that it is not much more than a glorified wireframe at this point.

![text]({{strapiUrl}}/uploads/f151477a52944fef8c40948a31c8bc8d.png)

There’s no styling of the generated page templates, no navigation between customers and orders and products, no authentication or authorization, customers and orders are linked at the database and model levels but there is nothing at the user interface level that visually or even logically ties these two concepts together. These are all behaviors that we’d want to implement or configure before we consider showing our application to our end users.

The CUBA version, on the other hand, is in a near shippable state as can be seen from this screenshot below.

![text]({{strapiUrl}}/uploads/977844ea7df1483dbcd023a5a2056e26.png)

It includes:

1.  Built-in UI theme
2.  Menu based navigation
3.  Built-in authentication and user management
4.  Built-in and flexible access control: CUBA allows both developers and authorized end users to restrict access to operations on entities, pages, and elements on pages based on roles and group membership – all from within the application.
5.  Automatic linking of associated entities in the UI (i.e you can lookup customers from the orders screen and and vice versa)
6.  Built-in and powerful search filters: users can create any number of filters on arbitrary combinations of fields (with potentially pre-populated values), save and share them with other users
7.  Raw data import and export capability for all tables
8.  Built-in Reporting
9.  System Profiler
10.  JMX console
11.  Drag and drop UI builder with data aware GUI widgets

The GUI builder alone more than makes up for the extra bit of work involved in setting up the application.

Obviously CUBA and Rails are very different frameworks. The purpose of this comparison between them is not to suggest that CUBA is a drop in alternative for Rails (or any of the other frameworks that I’ve mentioned above) or that CUBA is better than Rails or vice versa. My goal rather, is to demonstrate that for teams that are already invested in Java and need to build modern, dynamic, web-based business or enterprise applications – and do so relatively quickly – CUBA is a great choice. You get a lot of the ease of use of and productivity features provided by modern web frameworks like rails while avoiding the switching costs associated with switching to a new dev stack.

For our internal applications team here at Yieldmo, CUBA has been a game changer. We’ve been able to build applications in weeks that might have taken months. We’re in the process of migrating some internal applications written using technologies like React, Angular and Node.js. By using CUBA, we spend less time reinventing the wheel. We’ve even leveraged some of CUBA’s more advanced features to build our new flagship SAAS Engagement Management Platform (EMP™) product.

Of course there are some downsides. CUBA is still relatively unknown so it doesn’t have the huge open source community backing of more popular platforms. That being said, the core team and developer forums are great resources when you need help. CUBA is also an opinionated framework; as your application grows and your use cases expand you may find that there is your way and there is the CUBA way of implementing a feature. Experienced Java developers may have to unlearn some patterns and adopt new ones.

In the 10 months or so that I’ve been using CUBA I’ve been very pleasantly surprised by what the platform can do and look forward to learning more about it and seeing CUBA grow. I hope this post encourages you to do the same.

<a href="https://www.cuba-platform.com/quick-start-part-1" target="_blank"><code>Cuba Studio Quickstart 1</code><a>
<a href="https://www.cuba-platform.com/quick-start-part-2" target="_blank"><code>Cuba Studio Quickstart 2</code><a>
<a href="https://www.cuba-platform.com/quick-start-part-3" target="_blank"><code>Cuba Studio Quickstart 3</code><a>

<div class="citation"><div class="citation-line"></div><div class="citation-icon"></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Marketplace: Updates Summary]]></title>
            <link>https://www.jmix.io/cuba-blog/marketplace-updates-summary</link>
            <guid>https://www.jmix.io/cuba-blog/marketplace-updates-summary</guid>
            <pubDate>Tue, 16 Oct 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/67893d6a9e334b90bca5d3cb52e0a0c1.png">It’s been half a year since the launch of the [Marketplace](https://www.jmix.io/cuba-platform/marketplace/). Within this period we’ve carried out a number of improvements, such as new components publications and creating of a special forum category. Our community have done its bit for the Marketplace progress, and we expect to keep the same pace of our community and services development.]]></description>
            <content:encoded><![CDATA[It’s been half a year since the launch of the [Marketplace](https://www.jmix.io/cuba-platform/marketplace/). Within this period we’ve carried out a number of improvements, such as new components publications and creating of a special forum category. Our community have done its bit for the Marketplace progress, and we expect to keep the same pace of our community and services development.

Those six months have brought us more components, including such powerful tools as [CUBA CLI](https://www.cuba-platform.com/marketplace/cuba-cli) and [CUBA WebDAV](https://www.cuba-platform.com/marketplace/webdav). The full list looks the following way:

###### Components by Haulmont:

*   [Rich Search](https://www.jmix.io/cuba-platform/marketplace/rich-search) - designed to search for various types of objects like menu items using a single search field;
*   [Masquerade](https://www.jmix.io/cuba-platform/marketplace/masquerade) - a set of libraries for automating user interface testing and ensuring regressions get caught;
*   [LDAP](https://www.jmix.io/cuba-platform/marketplace/ldap) - enables integration with a directory server, including authentication, roles and access groups assignment;
*   [Global Events](https://www.jmix.io/cuba-platform/marketplace/global-events) - enables receiving Spring's application events on any application block of the distributed system;
*   [Multitenancy](https://www.jmix.io/cuba-platform/marketplace/multitenancy) - an implementation of a single database multi-tenancy support for CUBA applications;
*   [IMAP](https://www.jmix.io/cuba-platform/marketplace/imap) - enables email processing in a CUBA-based application via the IMAP protocol;
*   [CUBA WebDAV](https://www.jmix.io/cuba-platform/marketplace/webdav) - provides your CUBA application with powerful functionality for collaborative work on documents in various formats;
*   [CUBA CLI](https://www.jmix.io/cuba-platform/marketplace/cuba-cli) - a command line utility that enables you to easily create projects based on CUBA Platform;
<!--*   [Lori Timesheets](https://www.jmix.io/cuba-platform/marketplace/lori-timesheets) - an application allowing you to control and manage employees' time;-->

###### Components by community members:

*   [Wizard](https://www.jmix.io/cuba-platform/marketplace/wizard) - lets you create UI wizards through a specific UI component DSL (by Mario David);
*   [Testery](https://www.jmix.io/cuba-platform/marketplace/testery) - efficient exploratory testing with as much automation as possible ( by Mario David);
*   [Taggable](https://www.jmix.io/cuba-platform/marketplace/taggable) - lets you enhance your entities with a generic tagging functionality(by Mario David);
*   [Xero](https://www.jmix.io/cuba-platform/marketplace/xero) - lets you easily integrate with the Xero API (by Mario David);
*   [SW-responsive](https://www.jmix.io/cuba-platform/marketplace/sw-responsive) - a convenient wrapper for the corresponding Vaadin add-on (a component by Yury Artamonov);
*   [Duplicates Detection](https://www.jmix.io/cuba-platform/marketplace/duplicate-detection) - allows you to configure duplicates detection rules for entities (by 909 Technologies);
*   [Dynamic Columns](https://www.jmix.io/cuba-platform/marketplace/dynamic-columns) - adds dynamic (user created) columns support for Table components; (by Paolo Furini).

As you can see, both our team and community have done a great job. [Submit](https://www.cuba-platform.com/marketplace/suggest-component) your own component and become part of CUBA Team, too!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA WebDAV Addon Published]]></title>
            <link>https://www.jmix.io/cuba-blog/webdav-addon-published</link>
            <guid>https://www.jmix.io/cuba-blog/webdav-addon-published</guid>
            <pubDate>Thu, 11 Oct 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/bbc78fcd7210435aaea568080c0a86b3.png">The CUBA WebDAV Addon has been published on the Marketplace! The Addon provides your CUBA application with powerful functionality for collaborative work on documents in various formats. Automated migration from the standard CUBA file storage simplifies adding WebDAV support to existing projects.]]></description>
            <content:encoded><![CDATA[The CUBA WebDAV Addon has been published on the Marketplace! The Addon provides your CUBA application with powerful functionality for collaborative work on documents in various formats. Automated migration from the standard CUBA file storage simplifies adding WebDAV support to existing projects.

Key features:

*   Seamlessly open, edit and save documents in MS Office (and other applications that support WebDAV) apps straight from the server, without cumbersome manual saving to local disk and uploading back to server.
*   Visual components to work with files and versions for the generic CUBA UI.
*   Full support for collaborative work and file versioning, manageable both from the client application and CUBA UI.
*   Configurable conflict resolution policies.
*   Easy files access control management via full integration with CUBA Platform security subsystem.
*   Access to files from external systems using static links.
*   REST API.

The files and versions are stored on top of the standard CUBA file storage, so there is no need for an external WebDAV server.

WebDAV is a commercial addon, licensed separately from Studio. The addon is licensed per organization, so the price does not depend on the number of developers. Other terms are same as for the Premium Addons:

*   unlimited number of developers, servers and projects
*   access to the source code repository
*   the right to distribute the addon as part of your applications without restrictions
*   all upgrades during the subscription period
*   The right to continue using previously downloaded versions after subscription expiry

Trial version is included in <a href="https://www.cuba-platform.com/store#/store/studio-trial" target="_blank">Studio & Addons trial</a>. More information is available in the <a href="https://www.jmix.io/cuba-platform/marketplace/webdav" target="_blank">marketplace</a>.

_Note: if you already have a commercial Studio subscription, you can add WebDAV license to it in your <a href="https://www.cuba-platform.com/profile#/profile/" target="_blank">account</a>._]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Validation in Java applications]]></title>
            <link>https://www.jmix.io/cuba-blog/validation-in-java-applications</link>
            <guid>https://www.jmix.io/cuba-blog/validation-in-java-applications</guid>
            <pubDate>Mon, 08 Oct 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/0cc31a3a5f4c46e8b7418ad9517f8b47.png">This text discusses approaches to data validation. What are the common pitfalls that many projects fall into and what are the best practices Java applications should follow.]]></description>
            <content:encoded><![CDATA[<div class="red-box">
  This article is now out of date. Read the <a href="/blog/validation-in-java-applications-the-definitive-guide/">updated version here</a>.
</div>
<style>
  .red-box {
    background: #fff3f7;
    border: 1px solid #fc1264;
    color: #fc1264;
    border-radius: 16px;
    padding: 15px;
    margin-bottom: 20px;
    text-align: center;
  }
</style>

I often have seen projects that didn’t have almost any conscious strategy for data validation. Their teams worked under the great pressure of deadlines, unclear requirements and just didn’t have enough time to make validation in a proper and consistent way. So data validation code could be found everywhere: in Javascript snippets, Java screen controllers, business logic beans, domain model entities, database constraints and triggers. This code was full of if-else statements, was throwing different unchecked exceptions and it was just hard to find the right place where this damn piece of data could be validated... So, after a while, when project grew up enough it became quite hard and expensive to keep this validations consistent and following requirements, which as I’ve said are often fuzzy.
Is there a path to do data validation in an elegant, standard and concise way? The way that doesn’t fall ito a sin of unreadability, the way that helps us to keep most of the data validation logic together and which has most of the code already done for us by developers of popular Java frameworks?

Yes, there is.

For us, developers of <a href="https://www.cuba-platform.com/" target="_blank">CUBA Platform</a>, it is very important to let our users to follow the best practices. We believe that validation code should be:

1.  Reusable and following DRY principle;
2.  Expressed in a clear and natural way;
3.  Placed in the place where developers expects it to see;
4.  Able to check data from different data sources: user input, SOAP or REST calls etc.
5.  Aware about concurrency;
6.  Called implicitly by the application, without need to call the checks manually;
7.  Showing clear, localized messages to a user using concise designed dialogs;
8.  Following standards.

In this article I’ll be using an application based on CUBA Platform for all the examples. However, since CUBA is based on Spring and EclipseLink, most of this examples will work for any other Java framework that supports JPA and bean validation standard.

## DB Constraints Validations

Perhaps, the most common and straightforward way of data validation uses DB-level constraints, such as required flag (‘not null’ fields), string length, unique indexes and so on. This way is very natural for enterprise applications, as this class of software is usually heavily data-centric. However, even here developers often do mistakes, defining constraints separately for each tier of an application. This problem is often caused by splitting responsibilities between developers.

Let's take an example most of you faced with, or even participated :). If a spec says that the passport field should have 10 digits in its number, most probably it will be checked everywhere: by DB architect in DDL, by backend developer in the corresponding Entity and REST services, finally, by UI developer right in client source-code. Later on this requirement changes and size of the field grows up to 15 digits. Tech Support changes the DB constraint, but for a user it means nothing as the client side check will not be passed anyway...

Everybody knows the way to avoid this problem, validations must be centralized! In CUBA this central point of such kind of validation is JPA annotations over entities. Based on this meta information, CUBA Studio generates right DDL scripts and applies corresponding validators on the client side.

![text]({{strapiUrl}}/uploads/cf48fc1bbcfa49768110c90647e7e44b.png)

If JPA annotations get changed, CUBA updates DDL scripts and generate migration scripts, so next time you deploy your project, new JPA-based limitations will be applied to your application’s UI and DB.

Despite simplicity and implementation that spans up to DB level, and so is completely bullet-proof, JPA annotations are limited by the simplest cases that can be expressed in DDL standard without involving DB-specific triggers or stored procedures. So, JPA-based constraints can ensure that entity field is unique or mandatory or can define maximum length for a varchar column. Also, you can define unique constraint to the combination of columns with <span class="light-grey">@UniqueConstraint</span> annotation. But this is pretty much it.

However, in the cases that require more complex validation logic like checking for maximum and minimum values of a field or validating with a expression or doing a custom check that is specific to you application we need to utilize the well known approach called “Bean Validation”.

## Bean Validation

All we know, that it is a good practice to follow standards, which normally have long lifecycle and are battle-proven on thousands of projects. Java Bean validation is an approach that is set in stone in <a href="https://beanvalidation.org/specification/" target="_blank">JSR 380</a>, <a href="https://beanvalidation.org/specification/" target="_blank">349 and 303</a> and their implementations: <a href="https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/?v=5.3" target="_blank">Hibernate Validator</a> and <a href="http://bval.apache.org/" target="_blank">Apache BVal</a>.

Although this approach is familiar to many developers, it’s benefits are often underestimated. This is an easy way to add data validations even for legacy projects which allows you to express your validations in a clear, straightforward and reliable way as close to your business logic as it could be.

Using Bean Validation approach brings quite a lot benefits to your project:

*   Validation logic is concentrated near your domain model: defining value, method, bean constraint is done in a natural way that allows to bring OOP approach to the next level.
*   Bean Validation standard gives you tens of <a href="https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-defineconstraints-spec" target="_blank">validation annotations out of the box</a>, like: <span class="light-grey">@NotNull, @Size, @Min, @Max, @Pattern, @Email, @Past, less standard like @URL, @Length,</span> mighty <span class="light-grey">@ScriptAssert</span> and many others.
*   You are not limited by predefined constraints and can define your own constraint annotations. You can make a new annotation also, by combining couple others or make a brand new one and define a Java class that will be served as a validator.
*   For example, looking at our previous example we can define a class-level annotation <span class="light-grey">@ValidPassportNumber</span> to check that passport number follows right format which depends from the <span class="light-grey">country</span> field value.
*   You can put constraints not just on fields and classes, but also on methods and method parameters. This is called “validation by contract” and is the topic of the later section.

CUBA Platform (as some other frameworks) calls these bean validations automatically when user submits the data, so user would get the error message instantly if validation fails and you don’t need to worry about running these bean validators manually.

Let’s take a look at the passport number example once again, but this time we’d like to add couple additional constraints on the entity:

*   Person name should have length of 2 or more and be a well-formed name. Regexp is quite complex, but Charles Ogier de Batz de Castelmore Comte d'Artagnan passes the check and R2D2 does not :) ;
*   Person height should be in interval: 0 &lt; height &lt;= 300 centimeters;
*   Email string should be a properly formatted email address.

So, with all these checks the Person class looks like this:

![text]({{strapiUrl}}/uploads/82fa3baa89e7407c9a0abc5dc057b8b6.png)

I think that usage of standard annotations like <span class="light-grey">@NotNull, @DecimalMin, @Length, @Pattern</span> and others is quite clear and doesn’t need a lot of comments. Let’s see how custom <span class="light-grey">@ValidPassportNumber</span> annotation is implemented.

Our brand new <span class="light-grey">@ValidPassportNumber</span> checks that <span class="light-grey">Person#passportNumber</span> match the regexp pattern specific to each country defined by <span class="light-grey">Person#country</span>.

First, following the documentation (<a href="https://doc.cuba-platform.com/manual-6.9/bean_validation_constraints.html#bean_validation_custom_constraints" target="_blank">CUBA</a> or <a href="https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-class-level-constraints" target="_blank">Hibernate</a> docs are good references), we need mark our entity class with this new annotation and pass groups parameter to it, where <span class="light-grey">UiCrossFieldChecks.class</span> says that the check should be called after checking all individual fields on the cross-field check stage and <span class="light-grey">Default.class</span> keeps the constraint in the default validation group.

The annotation definition looks like this:

![text]({{strapiUrl}}/uploads/2d26be3ca16342879a862eb0affdffc0.png)

<span class="light-grey">@Target(ElementType.TYPE)</span> defines that the target of this runtime annotation is a class and <span class="light-grey">@Constraint(validatedBy = … )</span> states that the annotation implementation is in <span class="light-grey">ValidPassportNumberValidator</span> class that implements <span class="light-grey">ConstraintValidator&lt;...></span> interface and has the validation code in <span class="light-grey">isValid(...)</span> method, which code does the actual check in a quite straightforward way:

![text]({{strapiUrl}}/uploads/00e9cf7336824ae5b0f65b489a1e535d.png)

That’s it. With CUBA platform we don’t need to write a line of code more than that to get our custom validation working and giving messages to a user if he/she made a mistake. Nothing complex, do you agree?

Now, let’s check how all this stuff work. CUBA has some extra goodies: it not just shows error messages to a user but also highlight form fields that hasn’t passed single-field bean validations with nice red lines:

![text]({{strapiUrl}}/uploads/bdc4071d788a456ba64f67585045d336.png)

Isn’t this a neat thing? You got nice error UI feedback in the user's browser just after adding couple Java annotations to your domain model entities.

Concluding this section, let’s briefly list once again what pluses bean validation for entities has:

1.  It is clear and readable;
2.  It allows to define value constraints right in the domain classes;
3.  It is extendable and customizable;
4.  It is integrated with many popular ORMs and the checks are called automatically before changes are saved to a database;
5.  Some frameworks also runs bean validation automatically when user submits data in UI (but if not, it’s not hard to call <span class="light-grey">Validator</span> interface manually);
6.  Bean validation is a well-known standard, so there is a lot of documentation in the Internet about it.

But what shall we do if we need to set constraint onto a method, a constructor or some REST endpoint to validate data coming from external system? Or if we want to check the method parameters values in a declarative way without writing boring code full of if-elses in an each method we need to have such check?

The answer is simple: bean validation can be applied to methods as well!

## Validation by Contract

Sometimes, we need to make another step and go beyond just application data model state validation. Many methods might benefit from automatic parameters and return values validation. This might be required not just when we need to check data coming to a REST or SOAP endpoint but also when we want to express preconditions and postconditions for method calls to be sure that input data have been checked before method body executes or that the return values are in the expected range, or we just want to declaratively express parameters boundaries for better readability.

With bean validation, constraints can be applied to the parameters and return values of a method or constructors of any Java type to check for their calls preconditions and postconditions. This approach has several advantages over traditional ways of checking the correctness of parameters and return values:

1.  The checks don’t need to be performed manually in the imperative way (e.g. by throwing <span class="light-grey">IllegalArgumentException</span> or similar). We rather specify constraints declaratively, so we have more readable and expressive code;
2.  Constraints are reusable, configurable and customizable: we don’t need to write validation code every time we need to do the checks. Less code - less bugs.
3.  If a class or method return value or method parameter is marked with <span class="light-grey">@Validated</span> annotation, that the constraints check would be done automatically by the framework on every method call.
4.  If an executable is marked with <span class="light-grey">@Documented</span> annotation then it’s pre- and postconditions would be included in the generated JavaDoc.

As the result with the ‘validation by contract’ approach we have clear code, less amount of it which it is easier to support and understand.

Let’s look how does it looks like for a REST controller interface in the CUBA app. <span class="light-grey">PersonApiService</span> interface allows to get a list of persons from the DB with <span class="light-grey">getPersons()</span> method and to add a new person to the DB using <span class="light-grey">addNewPerson(...)</span> call. And remember: bean validation is inheritable! In other words, if you annotate some class or field or method with a constraint, all descendants that extends or implements this class or interface would be affected by the same constraint check.

![text]({{strapiUrl}}/uploads/dbcdb2a16dab4b66a2ff408351a2b4f3.png)

Does this code snippet look pretty clear and readable for you? <span style="color: grey;">(With the exception of <span class="light-grey">@RequiredView(“_local”)</span> annotation which is specific for CUBA platform and checks that returned Person object has all fields loaded from the <span class="light-grey">PASSPORTNUMBER_PERSON</span> table)</span>.
<span class="light-grey">@Valid</span> annotation specifies that every object in the collection returned by <span class="light-grey">getPersons()</span> method need to be validated against Person class constraints as well.
CUBA makes these methods available at the next endpoints:
*   <span class="light-grey">/app/rest/v2/services/passportnumber_PersonApiService/getPersons</span>
*   <span class="light-grey">/app/rest/v2/services/passportnumber_PersonApiService/addNewPerson</span>

Let’s open the Postman app and ensure that validation works as expected:

![text]({{strapiUrl}}/uploads/9c5c1ea4005a42cfad96e50c530d8039.png)

You might have noted that the above example doesn’t validate passport number. This is because it requires cross-parameter validation of the <span class="light-grey">addNewPerson</span> method since <span class="light-grey">passportNumber</span> validation regexp pattern depends from the <span style="color: grey;">country</span> value. Such cross parameter checks are direct equivalent to class-level constraints for entities!

Cross parameter validation is supported by JSR 349 and 380, you can consult <a href="https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-cross-parameter-constraints" target="_blank">hibernate documentation</a> for how to implement custom cross-parameter validators for class / interface methods.

## Beyond Bean Validation

Nothing is perfect in the world, and bean validation has has some limitations as well:

1.  Sometime you just want to validate an complex object graph state before saving changes to the database. For example you might need to ensure that all items from an order made by a customer of your e-commerce system could be fit in one of the shipping boxes you have. This is quite heavy operation amd doing such check every time users add new items to their orders isn’t the best idea. Hence, such check might need to be called just once before the Order object and it’s OrderItem objects are saved to the database.
2.  Some checks have to be made inside the transaction. For example, e-commerce system should check if there are enough items in stock to fulfill the order before committing it to the database. Such check could be done only from inside the transaction, because the system is concurrent and quantities in stock could be changed at any time.

CUBA platform offers two mechanisms to validate data before commit which <span style="font-size: 16px; font-weight:550;">are called <a href="https://doc.cuba-platform.com/manual-6.9/entity_listeners.html" target="_blank">entity listeners</a> and <a href="https://doc.cuba-platform.com/manual-6.9/transaction_listeners.html" target="_blank">transaction listeners</a>. Let’s look at them a bit more closely.</span>

### Entity Listeners

<a href="https://doc.cuba-platform.com/manual-6.9/entity_listeners.html" target="_blank">Entity listeners in CUBA</a> are quite similar to <span class="light-grey"> <a href="https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-checkconstraints-orm-hibernateevent" target="_blank">PreInsertEvent, PreUpdateEvent</a></span> <a href="https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-checkconstraints-orm-hibernateevent" target="_blank">and <span class="light-grey">PredDeleteEvent</span> listeners</a> that JPA offers to a developer. Both mechanisms allow to check entity objects before or after they get persisted to a database.

It’s not hard to define and wire up an entity listener in CUBA, we need to do two things:

1.  Create a managed bean that implements one of the entity listener interfaces. For validation purposes 3 of these interfaces are important:  
    <span class="light-grey">BeforeDeleteEntityListener<t>,  
    BeforeInsertEntityListener <t>and  
    BeforeUpdateEntityListener</t></t></span>
2.  Annotate the entity object that plan to track with <span class="light-grey">@Listeners</span> annotation.

That’s it.

In comparison with JPA standard (JSR 338, chapter 3.5) CUBA platform’s listener interfaces are typed, so you don’t need to cast Object argument to start working with the entity. CUBA platform adds possibility of entities associated with the current one or calling <span class="light-grey">EntityManager</span> to load and change any other entities. All such changes would invoke appropriate entity listener calls as well.

Also CUBA platform supports <a href="https://doc.cuba-platform.com/manual-6.8/soft_deletion.html" target="_blank">soft deletion</a>, a feature when entities in DB are just marked as deleted without deleting their records from the DB. So, for soft deletion CUBA platform would call <span class="light-grey">BeforeDeleteEntityListener / AfterDeleteEntityListener</span> listeners while standard implementations would call <span class="light-grey">PreUpdate / PostUpdate</span> listeners.

Let’s look at the example. Event listener bean connects to an Entity class with just one line of code: annotation <span class="light-grey">@Listeners</span> that accepts a name of the entity listener class:

![text]({{strapiUrl}}/uploads/940c0e4ea0dc40f5b763aedecf87a444.png)

And entity listener implementation may look like this:

![text]({{strapiUrl}}/uploads/b1913ba85919485898dca66b205a00b0.png)

Entity listeners are great choice when you:

*   Need to make data check inside transaction before the entity object get persisted to a DB;
*   Need to check data in the DB during the validation process, for example check that we have enough goods in stock to accept the order;
*   Need to traverse not just given entity object, like <span class="light-grey">Order</span>, but visit the object that are in the association or composition with the entity, like <span class="light-grey">OrderItems</span> objects for the <span class="light-grey">Order</span> entity;
*   Want to track insert / update / delete operations for just some of your entity classes, for example you want to track such events only for <span class="light-grey">Order</span> and <span class="light-grey">OrderItem</span> entities, and don’t need to validate changes in other entity classes during transaction.

### Transaction Listeners

<a href="https://doc.cuba-platform.com/manual-6.9/transaction_listeners.html" target="_blank">CUBA transaction listener’s</a> works in transactional context as well, but in comparison with entity listeners they get called for **every** database transaction.

This gives them the ultimate power:

*   nothing can pass their attention, but the same gives them weaknesses:
*   they are harder to write,
*   they can downgrade performance significantly if performing too much unneeded checks,
*   They need to be written much more careful: a bug in transaction listener might even prevent application from bootstrapping;

So, transaction listeners is a good solution when you need to inspect many different type of entities with the same algorithm, like feeding data to a custom fraud detector that serves all your business objects.  

![text]({{strapiUrl}}/uploads/e572f935e47043b685f6035edca0bfc4.png)

Let’s look at the example that checks if an entity is annotated with <span class="light-grey">@FraudDetectionFlag</span> annotation and if yes, runs the fraud detector to validate it. Once again, please note, that this method is called **<u>before every DB transaction gets committed</u>** in the system, so the code has to try to check as least objects as possible as fast as it can.

![text]({{strapiUrl}}/uploads/82e75602bd74449880deb9480710c6df.png)

To become a transaction listener, managed bean should just implement <span class="light-grey">BeforeCommitTransactionListener</span> interface and implement beforeCommit method. Transaction listeners are wired up automatically when the application starts. CUBA registers all classes that implements <span class="light-grey">BeforeCommitTransactionListener</span> or <span class="light-grey">AfterCompleteTransactionListener</span> as transaction listeners.

## Conclusion

Bean validation (JPA 303, 349 and 980) is an approach that could serve as a concrete foundation for 95% of the data validation cases that happen in an enterprise project. The big advantage of such approach is that most of your validation logic is concentrated right in your domain model classes. So it is easy to be found, easy to be read and be supported. Spring, CUBA and many libraries are aware about these standards and calls the validation checks automatically during UI input, validated method calls or ORM persistence process, so validation works like a charm from developer’s perspective.

Some software engineers see validation that impacts an applications domain models as being somewhat invasive and complex, they say that making data checks at UI level is a good enough strategy. However, I believe that having multiple validation points in UI controls and controllers is quite problematic approach. In addition, validation methods we have discussed here are not perceived as invasive when they integrate with a framework that is aware about bean validators, listeners and integrates them to the client level automatically.

At the end, let’s formulate a rule of thumb to choose the best validation method:

*   **JPA validation** has limited functionality, but is a great choice for simplest constraints on entity classes if such constraints can be mapped to DDL.
*   **Bean Validation** is flexible, concise, declarative, reusable and readable way to cover most of the checks that your could have in your domain model classes. This is the best choice in most cases once you don’t need to run validations inside a transaction.
*   **Validation by Contract** is a bean validation but for method calls. Use it when you need to check input and output parameters of a method, for example in a REST call handler.
*   **Entity listeners:** although they are not such declarative as Bean Validation annotations, they are great place to check big object’s graphs or make a check that needs to be done inside a database transaction. For example, when you need to read some data from the DB to make a decision. Hibernate has analogs of such listeners.
*   **Transaction listeners** are dangerous but ultimate weapon that works inside transactional context. Use it when you need to decide at runtime what objects have to be validated or when you need to check many different types of your entities against the same validation algorithm.

I hope that this article refreshed your memories about different validation methods available in Java enterprise applications and gave you couple ideas how to improve architecture of the projects you are working on.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Platform Training Course: Now Free on YouTube]]></title>
            <link>https://www.jmix.io/cuba-blog/training-course-now-free</link>
            <guid>https://www.jmix.io/cuba-blog/training-course-now-free</guid>
            <pubDate>Mon, 01 Oct 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/579983f8713a45619a435f466bc35875.png">Up until recently, this training course was part of our commercial content. Now we are releasing it for free to help the whole community use the framework and tools more efficiently.]]></description>
            <content:encoded><![CDATA[Up until recently, this training course was part of our commercial content. Now we are releasing it for free to help the whole community use the framework and tools more efficiently.

The course contains 7 videos:

*   Working with data
*   Customizing web application look and feel using themes and SCSS rules
*   Reporting
*   Displaying Charts and Maps
*   Business Process Management
*   Extending Platform Functionality
*   Deployment Options

Combined with already available free webinars, this forms a comprehensive video course, covering all key aspects of CUBA applications development. We hope that you’ll find these videos both a perfect starting point and a source of knowledge on specific aspects of development.

All training and educational videos are available on <a href="https://www.cuba-platform.com/webinars" target="_blank">this web page</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Meet CLI for CUBA Platform]]></title>
            <link>https://www.jmix.io/cuba-blog/cli-for-cuba-platform</link>
            <guid>https://www.jmix.io/cuba-blog/cli-for-cuba-platform</guid>
            <pubDate>Tue, 07 Aug 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/1ddebf921cbf4bae8eebefaa7b350613.png">There is no secret, that the world of software developers, especially Java developers, is full of keyboard maniacs who’d better type 10-15 letters over one mouse click. And our community is not an exception, therefore we've been frequently asked questions like "How can I start a project without CUBA Studio?" or "Is there light-weight free command line alternative to CUBA Studio?". So, good news everyone!]]></description>
            <content:encoded><![CDATA[There is no secret, that the world of software developers, especially Java developers, is full of keyboard maniacs who’d better type 10-15 letters over one mouse click. And our community is not an exception, therefore we've been frequently asked questions like "How can I start a project without CUBA Studio?" or "Is there light-weight free command line alternative to CUBA Studio?". So, good news everyone!

## Does Free CLI Replace Commercial CUBA Studio?

CLI is not seen as an alternative to CUBA Studio, it has another mission. CLI will be useful for developers who are experienced in Spring Framework, JPA and CUBA infrastructure, and (important!) feel comfortable working in a black window with gray letters. In a nutshell, cuba-cli is a command line utility that enables you to easily create projects based on CUBA Platform. Also, it provides the lightweight scaffolding of the main project artifacts: entities, screens, services, etc.

![text]({{strapiUrl}}/uploads/69c9ba6709e24fbea24467a1c93d22d3.png)

At the same time Studio keeps its niche providing a short track into CUBA world. It provides an intuitive user interface, where even a newcomer to CUBA can design their first application in minutes, even without any experience in JPA or Spring or any underlying technology… In fact, you don't need to put any line of code to develop a standard CRUD application - the Studio will do it for you. Also the Studio will be a great choice for people who are migrating to CUBA from another ecosystem and for the ones who got used to have an ultimate comfort in an IDE.

![text]({{strapiUrl}}/uploads/b074fa870c1b44b99629b65e6d45d8d8.png)

To sum up, CUBA Studio is more about "learning while doing" and a huge "time saver", while CLI is a workhorse that writes mandatory boilerplate routine for you.

## What CLI Can?

Obviously, you have to install CLI first. It supports major OSes and you can find the installation guide for each one <a href="https://github.com/cuba-platform/cuba-cli/wiki/Installation" target="_blank">here</a>. After installation just type _cuba-cli_ in your command line, and that's it - we are ready to start a new project or manipulate with an existing one. By tapping Tab you can find all supported commands listed. Choose or type the _help_ command and it will give you a short overview about every command. Let's look what these commands do behind the scene and how they save developer's time and make the lifetime of your keyboard longer:

### General Purpose

*   **help, version, exit, cd** - obviously, these commands do not affect your source code and their action is clearly understandable from the names, so let's jump over them :).

### Project Setup and Global Settings

*   **create-app** - guides through the required steps to create a new CUBA project: project name, namespace, root package, platform version and a database used in the project. The project will contain global (accessible from both core and web modules), core (server side layer for business logic) and web (server side layer for screen controllers and other GUI logic) modules.
*   **polymer** - adds a new client to your application, based on the Polymer library, developed by Google. It modifies _settings.gradle_ and _build.gradle_ by adding the configuration and tasks for the new module. It also creates files of required image resources and generates login, menu, and other useful web-components for your Polymer front-end application.
*   **theme** - creates a special structure of folders under the _modules/web_ directory, a few images to brand the application (login icon, menu icon and favicon) and a few scss files, where you can modify the default scheme. It also adds the _webThemesModule_ module and its configuration to the settings.gradle and build.gradle files. Finally, this command adds the _deployThemes_ gradle task to be able to see changes without server restart. <a href="https://doc.cuba-platform.com/manual-6.9/web_theme_extension.html" target="_blank">This part</a> of the documentation provides detailed information on this subject.
*   **add-component** - plugs an existing application component into your application. It adds new line into the dependencies block of your build gradle and modifies _web.xml_ of the web module adding the main package of the application component to the _appComponents_ context parameter.

### Domain Modeling

*   **entity** - generates a stub for JPA entity and its DDL script. This entity will be also registered in _persistence.xml_ or _metadata.xml_, depending on entity type - if it is persistent or not. Finally CLI will generate a message pack to provide localizations for entity attributes.
*   **enumeration** - generates an Enum implementing the EnumClass interface, its fields with localization messages and a useful _fromId_ method.

### Business Logic

*   **entity-listener** - scaffolds a Spring component implementing Entity Listeners interfaces and declares it in the corresponding Entity class. Such listeners are hooked when an entity changes its state. You can find more information <a href="https://doc.cuba-platform.com/manual-latest/entity_listeners.html" target="_blank">here</a>.
*   **service** - scaffolds an interface in the global module and its implementation in core. To be usable from the web module it gets registered in the _WebRemoteProxyBeanCreator_ bean definition in _web-spring.xml_.
*   **bean** - simply generates a Spring component and saves your time on typing around 150 chars :).
*   **config** - scaffolds a stub for a CUBA configuration interface in the specified module with the specified source type (System, DB or App). Find more information about CUBA configuration interfaces in <a href="https://doc.cuba-platform.com/manual-6.9/config_interfaces.html" target="_blank">this chapter</a> of the documentation.

### User Interface

*   **screen** - scaffolds a GUI screen. The command supports creating:  
    - a new empty screen  
    - extending an already existing one  
    - a browser - a screen with a list of entities, CRUD actions over them and a filter  
    - an editor - a screen for creating or editing a single entity.

The command scaffolds xml screen descriptor and its Java controller with its localization message pack. Optionally it can also add a screen to the main menu.

### Misc

*   **app-component** - turns your CUBA application to be embeddable (pluggable) into another CUBA application. Find more information about the concept of application components in the <a href="https://doc.cuba-platform.com/manual-6.9/app_components.html" target="_blank">documentation</a>. This command generates _app-component.xml_ file, that defines the dependencies on other components, describes the existing application modules, generated artifacts and exposed application properties. While running the command it will prompt to change your current module prefix to a unique one in order to avoid conflicts. If you change the prefix it will also adjust _settings.gradle_ and _build.gradle_ files.
*   **update-script** - creates an SQL update script file, meeting CUBA conventions for its place and name. CUBA Platform includes mechanism of applying update scripts on application start. These scripts should be executed in the historical order, from oldest to newest. To ensure such ordering update scripts should be placed under the _modules/core/db/update/{USED DATABASE}/{yy}/_ directory and named as _{yyMMdd}-{INCREMENT}-{SCRIPT NAME}.sql_.
*   **custom-template** - generates project files from velocity templates, defined by a developer. Templating mechanism allows to extend CLI command set declaratively and without compilation. Find more information about CLI templating engine <a href="https://github.com/cuba-platform/cuba-cli/wiki/Custom-templates" target="_blank">here</a>.

As you see CLI undertakes a large amount of work to protect a developer from boring, but inevitable routine.

## Extensibility

First of all, as it was already mentioned, CLI provides a template engine to extend its command set without the need to change the sources and recompile it. **CLI templates** consist of two parts:

1.  _template.xml_ file, that declaratively describes questions to be asked by a custom command.
2.  A set of files (xml, java, or any other format) with the <a href="http://velocity.apache.org/engine/1.7/user-guide.html" target="_blank">Apache Velocity</a> scripts in them, so that they could be processed by the Velocity template engine. Answers to the questions from the template.xml file will be passed as parameters and reachable in the Velocity scripts.

This <a href="https://github.com/cuba-platform/cuba-cli/wiki/Custom-templates" target="_blank">wiki page</a> provides the detailed information about the CLI templates.

Secondly, CLI provides extension points to load **custom plugins** and exposes public events which can be used in a custom plugin. Using this mechanism developers can create new commands with maximum flexibility as well as extend existing ones, e.g. add other options for the **screen** command, like lookup. You can find the documentation and development guide for CLI plugins <a href="https://github.com/cuba-platform/cuba-cli/wiki/Plugin-Development" target="_blank">here</a>.

Finally, CUBA CLI is an **open source** project and its source code is published on <a href="https://github.com/cuba-platform/cuba-cli" target="_blank">GitHub</a>. CUBA Team would be happy to see your contributions (see the <a href="https://github.com/cuba-platform/cuba-cli/blob/master/CONTRIBUTING.md" target="_blank">contribution guideline</a>) as well as <a href="https://github.com/cuba-platform/cuba-cli/issues" target="_blank">issues</a> you may face. So, if you see some common, but uncovered use case, feel free to help the community and send us your pull request!

## Conclusion

This is just the starting point of our CLI and we hope that it will help you to make the development process slicker and faster, especially if you are not using CUBA Studio. We are going to improve CLI further and already planning the roadmap - <a href="https://github.com/cuba-platform/cuba-cli/milestone/2" target="_blank">here</a> you can see the features we would like to release with the second version.

Concluding the article, I would like also to share a recommendation. Starting your first CUBA project, it might happen that CLI becomes too heavy lifting for the initial evaluation of the platform. CUBA Studio offers a <a href="https://www.cuba-platform.com/development-tools#cubastudio" target="_blank">30-day trial</a>, so, if you or your colleagues are new to the framework it is recommended to use CUBA Studio for the initial stage and interactively discover platform features. Since the trial is over, you can decide if you would like to subscribe and keep using CUBA Studio or move to CLI.

Finally, you can watch the CLI demo video on our <a href="https://www.youtube.com/watch?v=5nHeA57-628" target="_blank">youtube channel</a>.

P.S. Oh, yes, almost forgot to tell that CLI is written in Kotlin. This is the first time we are using this language in production - so far so good!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Vaadin Flow – a marvelous deer]]></title>
            <link>https://www.jmix.io/cuba-blog/vaadin-flow-a-marvelous-deer</link>
            <guid>https://www.jmix.io/cuba-blog/vaadin-flow-a-marvelous-deer</guid>
            <pubDate>Fri, 20 Jul 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/42f5757ad3a44f6d91714be6069bd6cc.png">As you probably know, Vaadin is one of the most popular web frameworks on Java. Most recently a new release of this framework for web UI development was issued – Vaadin 10.]]></description>
            <content:encoded><![CDATA[As you probably know, Vaadin is one of the most popular web frameworks on Java:

*   https://zeroturnaround.com/rebellabs/java-web-frameworks-index-by-rebellabs/
*   https://javapipe.com/hosting/blog/best-java-web-frameworks/

Most recently a new release of this framework for web UI development was issued – Vaadin 10.

The creators state Vaadin Flow as a new Java web framework for modern web apps and websites development (I don’t quite believe them here). It’s a part of Vaadin Platform which replaces another product – Vaadin Framework, it enables to develop web apps (and to be more precise, web UI) using Web Components standard on Java.

At this point, everything must have mixed up in a reader’s head, all those Vaadin Bla Bla, framework, platform and so on. What’s going on?

We’ve been using Vaadin as a part of <a href="https://www.cuba-platform.com" target="_blank">CUBA platform</a> for UI Back-office systems for 7 years and have accumulated a lot of working experience with it during this period, that’s why we can’t help but worry about its destiny. Below you will find my speculations on Vaadin 10.

## Vaadin Framework

Vaadin is a Finnish company which creates UI development tools and libraries. Also, they created a Java web development framework of the same name.

Vaadin Framework is a UI framework with a server-side programming model, in which all the UI logic and its state live on a server, and a web browser executes only the code of UI widgets. In fact, it is a thin client technology, where a browser reflects only what a server commands and all events are sent to a server.

![text]({{strapiUrl}}/uploads/a25a7eb2256549c68136ddcc6ffe3514.png)

The server-side approach enables us to forget that the development is designed for web and to develop UI as a desktop Java app with a direct access to data and services on a server. At the same time, Vaadin will take care of both UI reflection in a browser and AJAX interaction between a browser and a server. Vaadin engine provides application server-side user interface rendering in a browser and encapsulates all the details of exchange between a client and a server.

This approach has many advantages:

*   Java code is easier to write and debug
*   You can use well known Java libraries and tools (IDE, compilers, testing)
*   It is not necessary to develop and expose web-services
*   Solutions are more secure

And disadvantages:

*   Requires a lot of memory on a server for UI representation
*   It is harder to scale a solution
*   When developing widgets, you need to develop Java API

Due to those advantages and disadvantages, Vaadin FW firmly fixed in the enterprise development, where the loads are predictable, and development speed and simplicity are more important than the cost of hardware and memory.

## What happened to Google Web Toolkit

All the time that Vaadin is familiar to a wide audience, the client side of Vaadin FW was inseparably connected with another well-known product – Google Web Toolkit (GWT). This tandem enabled user to write the UI components and server API for them using the same language – Java, which was rather convenient.

The last few years Google Web Toolkit wasn’t upgrowing, and since 2015 we’ve been waiting for GWT 3.0 / J2CL announced at GWT.Create 2015:

*   <a href="https://www.youtube.com/watch?v=XJYNCohpxU0" target="_blank">https://www.youtube.com/watch?v=XJYNCohpxU0</a>
*   <a href=" https://groups.google.com/forum/#!topic/google-web-toolkit-contributors/s_kX17Xs1S4" target="_blank">https://groups.google.com/forum/#!topic/google-web-toolkit-contributors/s_kX17Xs1S4</a>
*   <a href="https://groups.google.com/forum/#!topic/Google-Web-Toolkit-Contributors/9Zi4-C5gpxQ" target="_blank">https://groups.google.com/forum/#!topic/Google-Web-Toolkit-Contributors/9Zi4-C5gpxQ</a>

During this stagnation period (2015-2017) an important event had happened: the new Web Components specification and another web framework by Google – Polymer appeared. Apparently, this was the beginning of the end of GWT.

It should be mentioned that GWT 3 is developed as an internal Google framework, and its development is kept inside the company. Therefore, the community can’t anyhow influence the process or at least see that the process is going.

Mentioning this stagnation, the Vaadin Team took a tough <a href="https://vaadin.com/blog/vaadin-s-frontend-direction" target="_blank">decision</a> to fully abandon the development on GWT and rewrite the client side of their framework. Those changes could not pass unnoticed and frightened everyone who has been already developing on Vaadin.

## Web Components

Web Components is a set of standards. It was offered and is actively promoted by Google, but the initiative has been already supported in Mozilla. In fact, those are technologies for creating web UI components so that they could support behavior and representation encapsulation. And the main advantage is the reusability.

See <a href="https://www.webcomponents.org">https://www.webcomponents.org</a> 

Basic concepts:

*   Custom Elements - an API for creating your own HTML elements
*   Shadow DOM – a tool of HTML components encapsulation and their visual representation isolation from global CSS rules. In a word, you can make a component, for example, an order form, and you shouldn’t worry that form styles will be broken because of the page’s global CSS rules.
*   HTML Templates – an opportunity to place passive blocks containing DOM draft elements in an HTML document. Such blocks are parsed by a browser but aren’t rendered and don’t execute their code. They are proposed to be used as a template for data rendering.
*   HTML Imports – a special syntax for importing any HTML document as a module with all its layout, styles and JavaScript code.

For example, if we look into the YouTube DOM tree, we’ll notice the usage of Custom Elements and Shadow DOM:

![text]({{strapiUrl}}/uploads/844bdc5a6fa447b9adbb74eb554c8063.png)

All those things enable to write modern web UI components.

Here I should admit that the support in browsers is far from perfection, and you still need <a href="https://www.webcomponents.org/polyfills/" target="_blank">polyfills</a>, for example, for Edge.

## Polymer

Polymer is quite a small library beyond Web Components standards composed to simplify their usage. Example:

<pre><code class="hljs cs"><span class="hljs-comment">// Import corresponding components</span>
import <span class="hljs-string">'@polymer/paper-checkbox/paper-checkbox.js'</span>;
import {PolymerElement, html} <span class="hljs-keyword">from</span> <span class="hljs-string">'@polymer/polymer'</span>;

<span class="hljs-comment">// Determine new class</span>
<span class="hljs-keyword">class</span> <span class="hljs-title">LikeableElement</span> <span class="hljs-title">extends</span> <span class="hljs-title">PolymerElement</span> {

&nbsp; <span class="hljs-comment">// Here will be the component’s public features</span>
&nbsp; <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">get</span> <span class="hljs-title">properties</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">return</span> { liked: Boolean }}

&nbsp; <span class="hljs-comment">// That’s how the DOM tree will look inside, CSS influences only the component itself</span>
&nbsp; <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">get</span> <span class="hljs-title">template</span>(<span class="hljs-params"></span>) </span>{
&nbsp;&nbsp;&nbsp; <span class="hljs-keyword">return</span> html`
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;style&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .response { margin-top: <span class="hljs-number">10</span>px; } 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/style&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;paper-checkbox <span class="hljs-keyword">checked</span>=<span class="hljs-string">"{{liked}}"</span>&gt;I like web components.&lt;/paper-checkbox&gt;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div hidden$=<span class="hljs-string">"[[!liked]]"</span> <span class="hljs-keyword">class</span>=<span class="hljs-string">"response"</span>&gt;Web components like you, too.&lt;/div&gt;
&nbsp;&nbsp;&nbsp; `;
&nbsp; }
}</code></pre>

See <a href="https://www.polymer-project.org/" target="_blank">https://www.polymer-project.org/</a>

In fact, Polymer does everything that was formerly done by GWT, but at the same time it is compatible with any JS components and other frameworks like React and Angular.

## Vaadin Components

Let’s go back to Vaadin. Quite for a while, Vaadin company has been developing a product named <a href="https://vaadin.com/components/browse" target="_blank">Vaadin Components</a> – UI components for frontend developers, which can be integrated into any JS applications. 

![text]({{strapiUrl}}/uploads/80f5b32254ee4512b8d5b4a2b437a640.png)

Those components are based on Web Components and Polymer!

As we see now, that was a backup plan for Vaadin Framework, which helped to abandon Google Web Toolkit and develop a new framework for which there weren’t any components. The chicken-and-egg problem was solved, and Vaadin Components became a front end of the upcoming Vaadin 10.

## Vaadin Flow

Vaadin 8 included a mechanism of UI state synchronization and two-way RPC protocol (remote procedures calls) support. It was possible only due to GWT, as shared interfaces of server and client classes were written on Java.

With giving GWT up it was necessary to implement a new mechanism which would enable to transparently integrate with JS frontend and Java backend. The role of such a mechanism was carried out by Vaadin Flow (that name was also used to call Vaadin 10 for a long time).

There is the following scheme in the documentation on Flow: <a href="https://vaadin.com/docs/v10/flow/introduction/introduction-overview.html" target="_blank">https://vaadin.com/docs/v10/flow/introduction/introduction-overview.html</a>

![text]({{strapiUrl}}/uploads/9570c3c6f0c44b7fab1c707d9a3f95ed.png)


Its main points are:

*   support of UI state synchronization from server to client
*   server side can subscribe to UI components events, with that AJAX query will be executed
*   business logic is performed on the server, web-browser is loaded only with data reflected in UI
*   server side uses Java
*   client side can use HTML, CSS, JS and Polymer templates

For me it means that Vaadin will have more frontend technologies, and Java won’t be enough (for Vaadin 8 you would need only Java, and HTML/CSS wouldn’t be necessary). On the other hand, now simple JS code integration is possible.

See the complete feature list in the documentation: <a href="https://vaadin.com/docs/v10/flow/Overview.html" target="_blank">https://vaadin.com/docs/v10/flow/Overview.html</a>

## Vaadin Platform

Every component of Vaadin 10 is developed separately and in the best traditions of JS world – tiny modules, maximum independence from each other. At the same time, the client part of components is packed in JAR in <a href="https://www.webjars.org/" target="_blank">WebJARs</a> format. 

It’s a bit frightening, especially if you look at the minimal project relations:

![text]({{strapiUrl}}/uploads/396fbc4743bb4742ad64a0ccdd628160.png)

In order to somehow manage this chaos, the BOM (bill of materials) project appeared, called <a href="https://github.com/vaadin/platform" target="_blank">Vaadin Platform</a>. 

It’s not a self-contained product, but only a list of compatible components and tools versions made in Maven <a href="https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html" traget="_blank">https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html</a>

It is connected to Maven in the following way: <a href="https://vaadin.com/docs/v10/flow/components/tutorial-flow-components-setup.html" target="_blank">https://vaadin.com/docs/v10/flow/components/tutorial-flow-components-setup.html</a>

<pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-title">dependencyManagement</span>&gt;</span>
&nbsp;&nbsp;&nbsp; <span class="hljs-tag">&lt;<span class="hljs-title">dependencies</span>&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-tag">&lt;<span class="hljs-title">dependency</span>&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-tag">&lt;<span class="hljs-title">groupId</span>&gt;</span>com.vaadin<span class="hljs-tag">&lt;/<span class="hljs-title">groupId</span>&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-tag">&lt;<span class="hljs-title">artifactId</span>&gt;</span>vaadin-bom<span class="hljs-tag">&lt;/<span class="hljs-title">artifactId</span>&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-tag">&lt;<span class="hljs-title">version</span>&gt;</span>${vaadin.platform.version}<span class="hljs-tag">&lt;/<span class="hljs-title">version</span>&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-tag">&lt;<span class="hljs-title">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-title">type</span>&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-tag">&lt;<span class="hljs-title">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-title">scope</span>&gt;</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-tag">&lt;/<span class="hljs-title">dependency</span>&gt;</span>
&nbsp;&nbsp;&nbsp; <span class="hljs-tag">&lt;/<span class="hljs-title">dependencies</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">dependencyManagement</span>&gt;</span></code></pre>

## Migration from Vaadin FW 8

The migration options with Vaadin 8 are described in this document:

<a href="https://vaadin.com/docs/v10/flow/migration/1-migrating-v8-v10.html" target="_blank">https://vaadin.com/docs/v10/flow/migration/1-migrating-v8-v10.html</a>

Here I have some bad news for you: if you’ve coded a huge project on Vaadin 8, you’ll have to fully rewrite it in the conversion to Vaadin 10\. There is no migration path at all!

Vaadin 10 and Vaadin 8 are similar in several aspects:

*   Server-side approach
*   Java for UI logic development
*   The same approach to data binding

The bottom line is: **Vaadin 10 is a new framework made from scratch.**

As Vaadin developers <a href="https://vaadin.com/blog/the-revaadin-platform" target="_blank">promise</a>, Vaadin 8 will be supported until 2022, probably new approaches to migration will appear. 

## Conclusion

I consider important the fact that the new Vaadin website is created on Vaadin Flow. Previously the maturity of a programming language was defined as whether its compiler was coded on the same language. This now de-facto becomes a standard for frontend technologies.

I hope now you can make up your mind about Vaadin 10\. On the whole, it’s a good enough framework and a great groundwork for the future. For me, it’s an excellent experimental space for new ideas and approaches to UI building.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Convert Legacy Applications into Future Proof Apps]]></title>
            <link>https://www.jmix.io/cuba-blog/legacy-applications-versus-modern-applications</link>
            <guid>https://www.jmix.io/cuba-blog/legacy-applications-versus-modern-applications</guid>
            <pubDate>Wed, 11 Jul 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/787a62abbcdf44eb877732a3ed97b512.jpg">COBOL, 4GL, minicomputers… - this terminology sounds forgotten nowadays together with phonograph records and punch cards. Unbelievably, in the enterprise world you still can meet these dinosaurs functioning, especially in big companies like international banks or world-wide manufacturers.

]]></description>
            <content:encoded><![CDATA[COBOL, 4GL, minicomputers… - this terminology sounds forgotten nowadays together with phonograph records and punch cards. Unbelievably, in the enterprise world you still can meet these dinosaurs functioning, especially in big companies like international banks or world-wide manufacturers.

Migrating legacy to modern tech stack has always been the core business and main expertise of Transformix - a software development company based in San Diego, CA. Mixing their vast experience in modernizing legacy software with CUBA Platform features they show great results in this area. Learn more about their experience in this article.

<div class="citation"><div class="citation-line"></div><div class="citation-icon"></div></div>

# Legacy Applications vs. Modern Applications

Charles Finley, original post is <a href="http://modernization.xformix.com/2018/06/26/blog-2/" target="_blank">here</a>

At the risk of over simplification, I believe that a “modern application” can be illustrated with the help of the image in Figure 1\. For the most part, when legacy applications are mentioned one usually thinks of monolithic applications that were written in older programming languages such as COBOL with terminal based user interfaces that usually use data stores such as ISAM, flat files and proprietary database management systems. The left most bottom of the diagram shows this type of application. As the diagram shows, application architectures have evolved into web and mobile user

![text]({{strapiUrl}}/uploads/9434076398094c7da2d8a0644a29219b.png)

Figure 1 – Modern Application

Interfaces that can be loosely coupled with external applications often based in the cloud. The diagram does not show that applications developed today are most often able to be hosted on virtualized servers and/or in containers. The diagram also does not show that applications developed today are developed with newer programming languages and with a number of different database technologies.

This dichotomy between legacy applications both from a feature and usability point of view and from the point of view of the cost and relative difficulty to host the applications provide increasingly strong motivations for stakeholders to replace or modernize these legacy applications.

## What is the CUBA-Platform?

The <a href="https://www.cuba-platform.com/framework" target="_blank">CUBA-Platform</a> provides a full-stack architecture for building 3 tier applications and includes widely used common features for enterprise apps such as soft deletion, data-aware components, file storage, as well as high level modules: authentication and authorization, audit of data and others. This class is most appropriate for developing ERP-like systems, line of business applications or custom software for the corporate segment.

On the surface, the CUBA-Platform seems to be mainly suited to building custom applications from scratch. However, a closer look reveals a platform that provides the ability to reuse existing databases, auto generate domain models from existing databases, automatically create REST APIs from existing artifacts, standardize front-end by using prebuilt responsive UI templates, turn existing business logics into standard services and integrate any REST based third party services without coding. These features make the CUBA-Platform ideally suited for integration of a full stack JAVA framework with legacy applications.

## What are TransformixTools?

TransformixTools for CUBA-Platform are a number of custom engineering components and adapters that link legacy applications to the CUBA Platform among these are database adapters, terminal screen adapters, COBOL services integration components, Eclipse plugins, etc. These tools serve as CUBA-Platform plugins to facilitate the integration of the legacy application to CUBA features.

## What is ModernizationInPlace™

For the stakeholders of legacy applications for enterprise customers, ModerinzationInPlace™ is an innovative approach to software development and efficient open source technology that helps developers integrate existing legacy applications with the full stack CUBA-Platform enterprise development framework. This non-invasive approach transforms the application into a multi-model development platform in which existing tools can be used to extend and enhance existing legacy application code while at the same time modern development tools can be used to enhance and extend application functionality. Therefore, ModernizationInPlace™ makes customizations and upgrades to the application functionality relatively painless.

Main characteristics:

1.  ModernizationInPlace™ is a framework for enhancing the application’s business layer (with web service APIs) and database
2.  Tools from Transformix allow the application user interface to be supplemented with browser access which allows combining existing internal applications screens, like Legacy applications (mainframe green screen applications), with external Web services and Web pages with standard Web sites designed without integration interfaces (APIs), XML information and databases.
3.  The CUBA-Platform an open source full stack JAVA framework provides an open source foundation.
4.  Based on a JAVA technology stack, using best practices for designing business application’s database, business layer object model and web API
5.  No hidden magic, the generated server application is a regular REST web services that can be debugged using its source and the popular JAVA IDE’s.

## Toward the Multi-model Applications Platform

![text]({{strapiUrl}}/uploads/4422ee4ad64d44a4a2a59df6a8ac05a9.png)

Figure 2 – Multi-model Applications Platform

Yes Virginia it is possible to have your cake and eat it too. At least in so far as legacy applications are concerned. By that I mean it is possible to allow for continuing development in the legacy paradigm in parallel with development in newer paradigms. Figure 2 illustrates an environment in which an application that was built for an HP 3000 in COBOL with a proprietary HP TurboIMAGE database management system has been migrated to Linux with a PostgreSQL RDBMS. This is done with only minimal changes to application sources. In this environment the COBOL applications still use the same APIs they used on the HP 3000\. For example, database calls are TurboIMAGE calls and screen IO calls are VPLUS calls. However, using the combination of the CUBA-Platform with the TransformixTools enhancements makes it possible to show the terminal based user interface in a web browser and the database can be accessed using SQL. Therefore, at the same time that the legacy programs are used the application can be enhanced in much the same way as a newly developed JAVA based CUBA application is enhanced. Further, the developers who work on the application as a CUBA application do not need to have an HP 3000 knowledge or skills to do their jobs.

## Five Steps to ModernizationInPlace™

Figure 3 provides a high level overview of how the Multi-model Applications Platform is implemented. A SQL accessible database is needed in order to take full advantage of the features the CUBA-Platform has to offer. Therefore, the first step is to migrate the application data access to allow for multi-model SQL access. This means that the original application will still be able to access the data using the original APIs while at the same time other applications such as CUBA will be able to use SQL to access that same data. Step two is to allow browser access to the application screens. In this second step also includes the installation of the CUBA-Platform alongside the application. The application takes on the characteristics of a multi-model application once the CUBA-Platform is installed. This means that from then on the application can be extended and enhanced with modern tools by developers with little or no knowledge of the legacy programming environment.

What follows is an expanded version of the 5 steps toward a multi-model applications platform.

### Step One - A Multi-model Data Platform

A commonly used “trick” in migrations is to provide a simulated legacy system API on top of a relational database. This allows the existing application to access the data using the same database calls or APIs as always while at the same time providing alternative industry standard interfaces to newer and commercially available off the shelf applications. This is the approach Transformix uses. Here are some examples:

#### HP 3000 TurboIMAGE or Eloquence Database to RDBMS

TransformixTools provides a TurboIMAGE API that allows applications originally written for the HP 3000 to have the data and schema’s migrated to Oracle, PostgreSQL, MSSQL, IBM DB2 or IBM Informix with few or no changes to the application programs. Other applications can then access the data using standard APIs such as SQL.

#### MS Access to RDBMS

Microsoft Access lets you easily create databases to store and present your data in forms and reports. When starting, a database may be very simple and trivial, but over time, it may become more important as you add data, features, and even share it with others. It gains a life of its own and the overall design becomes critical.

![text]({{strapiUrl}}/uploads/7009e33a664b4b43a4083b9f43d721b3.jpeg)

Figure 3 – ModernizationInPlace 5 Steps

One of the most important architectural designs is splitting the database into a front-end and back-end database. This is how Access is designed to let you support multiuser databases and significantly simplify how you enhance the application over time.

Separating your application and data databases enables you to support multiple users and upgrade the application without wiping out their data. Assuming the application doesn’t change that often, the separation also makes it easier to just backup the data database since only that is changing every day.

Splitting a database is a relatively simple concept. You take an existing Access MDB/ACCDB database with its tables, queries, forms, reports, macros, modules, etc. and divide it into two databases:

*   The “Back-End” database just contains the tables
*   The “Front-End” database contains the application objects (everything except the tables) and links to the tables in the back-end database

This design is especially useful in multi-user environments where the back-end database is stored on a network and contains the shared data. Each user then has a copy of the front-end database on their desktop pointing to the shared database.

In multi-user environments, the front-end database can also contain tables that are private to the user. These local tables can store the user’s settings, selections, temporary or intermediate tables for processing data or reports, etc.

Once the database is split, using ODBC to access it from MS Access and using MS Access as a frontend allows the backend to be access with the CUBA-Plaform.

#### Microfocus ISAM to Ctree

FairCom’s No+SQL technology provides flexibility with an ISAM application’s data architecture by allowing data ISAM of any type to be stored within your record structure, without pre-defined schemas. At the same time, it supports industry-standard SQL (relational) interfaces and high-performance NoSQL (non-relational) interfaces to the same data at the same time.

C-treeACE is an ANSI-compliant SQL database with support for everything you expect from an RDBMS including stored procedures, triggers, user-defined functions, ODBC, JDBC, and a wealth of standard interfaces. c-treeACE provides simultaneous access to the same data via NoSQL interfaces for the ultimate in performance.

TransformixTools provides a CUBA-Platform interface to C-tree SQL.

#### Informix 4GL to Aubit4gl and RDBMS

Aubit 4GL project is a Open Source project to make a free, GNU/GPL, Informix-4GL and x4GL compatible development tools (compiler, tools, libraries), and continue to extend functionality and tools needed to write most efficient, stabile and productive applications in business related, database oriented applications. Aubit 4GL compiler is software that translates x4GL programming language into executable programs, enabling fast and productive creation of database oriented applications utilizing 4GL with embedded SQL and C programming languages, using ODBC and native connections to databases, and GTK+ for GUI, or Ncurses for CUI, and HTML/JavaScript for web browser presentation layers.

Once the database is in RDBMS CUBA-Platform can be used to extend and enhance the application.

### Step Two - Browser UI

TransformixTools provides solutions based on the CUBA-Platform and Vaadin that turn legacy application user interfaces into browser based interfaces.

#### Terminal Emulation

Our terminal emulation solution provides an instant web browser based terminal emulator to key business systems, including UNIX, VMS system, on any device with zero client software installation, all centrally managed. The Transformix solution is based on the CUBA-Platform. Therefore, at this step the CUBA-Platform is installed and made available to the application developers. Example Stansoft Aubit4gl.

#### VPLUS API Intercept

Another technique we use is the terminal API intercept approach. The best example is our VPDM HP VPlus replacement. We convert the HP VPLUS forms file to JAVA classes and create an xmlrpc-based intercept library that implements a plug-compatible replacement for VPLUS calls.

#### MS Access Forms

This solution is based on the CUBA-Platform as well. The TransformixTools DBForms solution includes software tools that turn MS Access forms to web pages written in JAVA code and available for viewing through Internet browser. A prerequisite step is to turn MS Access tables and queries into in their turn are converted to RDBMS. For now, this solution is limited to PostgreSQL.

### Step three - Enhanced Browser

A composite application (also known as a “Mashup”) is a Web site component or application displaying mixed content combined from heterogeneous sources. End-users don’t have to know from which underlying sources and applications this aggregated information is coming. In its simplest implementation, adding relatively simple external enhancements to a legacy user interface such as dropdowns or type-ahead search can greatly enhance the user experience with the application. These two features require database access that is separate from the original application and they can be implemented without modifying the original application. Figure 4 shows how what the user sees on their desktop is a further composite of the original application screen and a Google Map which is made available through a REST API and the CUBA-Platform. This too does not require a modification of the original application.

![text]({{strapiUrl}}/uploads/4059410e9caa4ae9a75fed67edb52f6e.jpg)

Figure 4 – Composite Application Screen

The use of the CUBA-Platform in Step Two is not only of benefit for creating the browser UI in the first place, it also makes it possible to extend and enhance the application from the user’s point of view without changing the original application.

### Step Four - Mobile and Web Services

The CUBA-Platform was introduced to the application environment in Step Two as a vehicle to facilitate enhancing the user interface to the application. Step Three gave us the opportunity to explore how CUBA can help further enhance user interfaces. In Step Four we begin to look at the real power of the platform. It provides a no Code and Low Code Platform that allows you to reshape how you interact with your legacy UNIX, or VMS system as well as your Windows, Linux or MAC system. With legacy terminal based applications as we have seen it gives us tools to help change green screen user experiences into contemporary interfaces that are delivered over the web. This gives you the freedom to adapt and evolve business processes, quickly realizing new efficiencies and gaining instant ROI and tactical advantages that are simply not available elsewhere, what’s more, this can be done by a super user or Citizen Developer.

#### Web Services

REST APIs are all the rage these days. The use of REST and other HTTP(S) based APIs have become the lingua franca of the world of computing. The CUBA-Platform is built on top of REST APIs and it plays very well with REST APIs provided by others. The use of CUBA as a modernization foundation for legacy systems transforms your host environment into a dynamic component of your business systems interface layer, normally confined to the transaction layer of the enterprise, these new tools will unleash your investment in your host system to freely interact with and feed tertiary business systems, increasing the availability, timeliness and integrity of key business data.

#### A Bit More About Developing with the CUBA Platform

At its highest level, the CUBA-Platform consists of the Design time CUBA Studio which works in concert with either Intellij IDEA IDE or Eclipse IDE. At runtime, it uses a JAVA application server, usually, Apache Tomcat.

![text]({{strapiUrl}}/uploads/1dd35297786d40278d0b876b72310d42.png)

Figure 5 – CUBA High Level Overview

CUBA Studio is a specialized tool for <a href="https://www.cuba-platform.com/rapid-application-development/" target="_blank">rapid application development</a> that streamlines building applications upon CUBA Platform. With Studio, applications are up and running within minutes. It also accelerates modernizing legacy applications by scaffolding the data model and CRUD UI on top of an existing database.

Studio is designed to be used in parallel with a Java IDE (Figure 6) , so developers do not have to abandon their beloved working environments. The focal point of the development process is the studio. Projects are open in Studio and most of the configuration and enhancement is managed with Studio in conjunction with the IDE. Moreover, testing and debugging are managed through Studio as well.

![text]({{strapiUrl}}/uploads/6af6bc2cea41452f81d9a9d06ead03e4.png)

Figure 6 – Studio with IDE

Applications developed using the CUBA Platform occupy three tiers as shown in Figure 7, they are, the database tier, the middle tier and the client tier. These tiers are connected using REST and HTTP APIs.

![text]({{strapiUrl}}/uploads/11725c74c07846dda17d6b9ef310e2a8.png)

Figure 7 – CUBA High Level Application Architecture

Using this architecture, the same backend can be used for web, desktop, mobile and REST API applications.

### Step Five - loosely Coupled Web Services

One of the most important ideas in the world of software engineering is the concept of loose coupling. In a loosely coupled design, components are independent, and changes in one will not affect the operation of others. This approach offers optimal flexibility and reusability when components are added, replaced, or modified. Components that can operate independently and have a well-defined communication channel are loosely coupled.

The architecture of the CUBA-Platform is built to support this loose coupling of components. Therefore, when legacy applications are integrated with the CUBA-Platform it allows their features and components to be used with the same flexibility as more recently developed application components.

## Summary and Conclusions

ModernizationInPlace™ is the Transformix Computer Corporation approach for converting legacy applications into future-proof enterprise applications with the CUBA-Platform. This approach helps organizations create a multi-model applications platform that allows legacy applications and application extensions written in the CUBA-Platform provided full stack JAVA framework to work side by side. Using this approach the sought after benefits of application modernization are achieved quickly and at low risk.

<div class="citation"><div class="citation-line"></div><div class="citation-icon"></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA - a big shift from Spring?]]></title>
            <link>https://www.jmix.io/cuba-blog/developing-with-cuba-a-big-shift-from-spring</link>
            <guid>https://www.jmix.io/cuba-blog/developing-with-cuba-a-big-shift-from-spring</guid>
            <pubDate>Tue, 03 Jul 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/945316829f03417099233f9ca695e45c.png">Reading requirements for yet another web project for internal corporate use you (at least myself) usually see a pretty common set: well-defined data storage structure (or sometimes it’s an existing legacy DB), lots of forms for data entry, quite complex business logic, reporting and integrations with lots of existing corporate systems from accounting to supply management, thousands of concurrent users. What are your first thoughts?]]></description>
            <content:encoded><![CDATA[Reading requirements for yet another web project for internal corporate use you (at least myself) usually see a pretty common set: well-defined data storage structure (or sometimes it’s an existing legacy DB), lots of forms for data entry, quite complex business logic, reporting and integrations with lots of existing corporate systems from accounting to supply management, thousands of concurrent users. What are your first thoughts?


“OK, I’ll take a well-known RDBMS, Hibernate/JPA+Spring Boot, add REST API and use my favourite/the latest JS framework to implement UI.“

“Ah. And I need to set up Spring Security. And maybe add some custom code to protect data at row level. How will I implement it? Probably database views or virtual private database.“

“And all these DAOs - they are similar and boring but I need to implement them.”

“And use something like <a href="http://modelmapper.org/" target="_blank">ModelMapper</a> to convert JPA Entities to DTOs for REST.”

“And don’t forget to tell John - our new intern - about lazy fetching and JPA joins.”

“Oh boy, can I get rid of all this routine stuff and focus on the critical piece of business logic implementation instead of implementing yet another login form and Entity-to-DTO conversion?“


This article is for developers who have implemented at least a couple of projects from scratch using the Spring framework (including Spring Boot) and now thinking about boosting their productivity. In the article I will show you how to get rid of very common time-killing routine tasks by using CUBA platform.

## Another Framework Again?

![text]({{strapiUrl}}/uploads/9ade0a7b5dda4faf9f09a89da3e6af14.png)


The number one question from developers when they hear about a new framework is: “Why do I need this when I can take Spring Boot and implement everything from scratch as I used to?”. Well, fair enough - new platform requires learning new principles and dealing with new limitations, leaving all years of your experience behind. Even if your current framework is not brilliant, you know it all, you know all the pitfalls and workarounds for them.

But what if I tell you that CUBA does not require a U-turn (or even right angle turn) from the traditional Spring-way of development, but a slight step aside that allows you to eliminate boilerplate noise as hundreds of lines of DTOs and conversion utils, implementation of data pagination or data filtering components, creating configuration files for Spring Security (JPA, Cache,... you name it).

We will start from the beginning and then show how CUBA application development follows the model that is used for almost all Spring-based applications will let you use all your Spring kung-fu skills that you’ve learned in your developer’s career and deliver more at the end. The article is focused on back-end code to make our story smaller and more concise.

## Spring Application Architecture

The typical architecture of a Spring application can be googled easily and in 90% of cases it can be represented as a three-layered application with some cross-cutting areas. Let’s have a look at a “classic” Spring application.

![text]({{strapiUrl}}/uploads/9288d6b94bac4fb0badd60cb3b7a5cb1.png)

**Domain Model** - usually created manually. There are some tools for creating a domain model based on a datastore structure though.

**Repository Layer** - classes that work with a data storage. Also known as “DAOs”, “Repositories”, etc. That’s where all those ORM frameworks (and their siblings) rule. It usually contains classes that perform CRUD operations using only one entity class from a domain model.

**Service Layer** - sometimes developers create an additional layer to separate business logic and data CRUD operations. This layer is useful if you have a complex business logic involving different types of data sources, external service integrations, etc.

**Web/Controllers Layer** (REST/MVC) - set of classes that deal with either REST API (that will be consumed by browser-based applications) or views implemented using JSPs, template frameworks (thymeleaf, velocity), or JVM frameworks (GWT, Vaadin, Wicket, etc.). Usually controllers manipulate DTOs rather than entity objects, due to API structure or representation in views. Therefore developers often have to implement bi-directional conversion between an entity model and a DTO model.

![text]({{strapiUrl}}/uploads/808c11ecaec544e7afdf7c27a598653f.png)

_If all above sounds familiar (and even like “Captain Obvious” to you) - it is a great sign meaning that you will be able to get started with CUBA with no barrier._

## Reference Application – Pet Clinic

They say: “Words are cheap, show me your code”. Spring has its own well-known “reference” application - Pet Clinic, which is available on <a href="https://github.com/spring-projects/spring-petclinic" target="_blank">GitHub</a>. Below we will show how your Spring Developer’s skills can be used when developing a backend for the new fork of the Pet Clinic - with CUBA now. There is a very good and detailed description of the reference application from Antoine Rey <a href="http://fr.slideshare.net/AntoineRey/spring-framework-petclinic-sample-application" target="_blank">here</a>; we will repeat some pieces in this article though.

![text]({{strapiUrl}}/uploads/48f4b069e17b4b5fa170e2d598f6abec.png)

### Data Model

ER diagram of the database is shown on the diagram. The actual object domain model in the application’s code is a bit more complex and includes some inheritance, you can find UML in the <a href="https://image.slidesharecdn.com/2017-01-springframeworkpetclinic-170209204315/95/spring-framework-petclinic-sample-application-5-638.jpg?cb=1486673606" target="_blank">presentation</a> mentioned above.

### Repository Level

There are four repositories to deal with main entities: Owner, Pet, Visit and Vet. Those repositories are based on Spring JPA framework and contain almost no code thanks to Spring JPA, but you can find a custom query in Owner repository to fetch owners and their pets in one request.

### UI Screens

The application consists of nine screens that allow us to view all data and edit some of it: pet owners, pets and visits. We won’t talk about them now, but I need to mention that those screens are just a simple CRUD forms that are pretty common for the most data-oriented applications.

### Additional Features

Apart from simple CRUD functionality the application provides some (not so obvious) functionality that shows the power of the Spring Framework:

*   Caching - vets list is cached, so there are no queries to DB when vet list is refreshed.
*   Validator - checks if all fields are filled during creating a new record about a pet.
*   Formatter - for proper display of a pet type.
*   i18n - the application is available in English and German languages.
*   Transaction management - some db queries are made read-only.

### A Side Note

![text]({{strapiUrl}}/uploads/4a883d0c08674c9b9a54af5ebf96ad86.png)


I like this picture very much since it reflects my feelings with 100% accuracy. To use any framework efficiently you need to understand how it works inside. For example Spring Boot hides a lot of things from you and you will be surprised how many classes lay behind one simple JPA interface initialization. Some notes about “magic” happening in Spring Boot Pet Clinic application:

*   There is no cache configuration code apart from @Caсheable annotation, but somehow Spring Boot “knows” how to set up a cache implementation (EhCache in our case).
*   Repositories are not marked as @Transactional (neither is their parent class org.springframework.data.repository.Repository), but all save() methods work just fine there.

But despite of all these implicits Spring Boot is a very popular framework because it’s transparent and predictable. It has a very detailed documentation and it’s open source, so you can read how things work and drill down into any method and see what’s going on there. I guess everyone likes transparent and manageable frameworks - using them makes your application maintainable.

## Pet Clinic with CUBA

_So, let’s have a look at a Pet Clinic implementation with CUBA Platform, try to look at it in terms of our Spring knowledge and figure out where we can save some efforts._

Source code for the Pet Clinic implementation can be found on <a href="https://github.com/belyaev-andrey/cuba-petclinic" target="_blank">GitHub</a>. Apart from that CUBA Platform has very good <a href="https://doc.cuba-platform.com/manual-latest/manual.html" target="_blank">documentation</a> and you can find almost everything there (most cases are illustrated with <a href="https://github.com/cuba-platform" target="_blank">examples and code snippets on GitHub</a>). In this article we will refer to the documentation quite often just to avoid explaining things twice.

### CUBA Application Architecture

![text]({{strapiUrl}}/uploads/e6747f63019b4f5d85f47817c0872642.png)

CUBA application consists of the following <a href="https://doc.cuba-platform.com/manual-latest/manual.html#app_modules" target="_blank">modules</a> (see the diagram).

**Global** - contains entities mapped to a database, CUBA views and service interfaces that can be used in other modules.

**Core** - all service implementations that work with the application’s database and implement business logic should be placed here. Please note that Core classes are not available in other modules, it was done on purpose to provide separate <a href="https://doc.cuba-platform.com/manual-latest/manual.html#deployment_variants" target="_blank">deploy</a> of Core and GUI modules to different servers for better scalability. To inject services from Core module to other modules you should use interfaces declared in Global module.

**GUI, Web, Desktop, Portal** - these modules contain GUI-related classes (controllers, listeners, etc.) responsible for UI events processing. You can create your custom REST controllers here to complement <a href="http://files.cuba-platform.com/swagger/6.9/" target="_blank">out-of-the-box REST API</a> that CUBA generates for you.

For a better developer’s performance CUBA has <a href="https://www.cuba-platform.com/development-tools" target="_blank">Studio</a> - a nice small GUI to create and register entities that will change all the configs for you, help with creating code stubs for services and has a WYSIWYG editor for GUI forms.

So an application based on CUBA Platform consists of two (or more) separate modules - Core and GUI(s) that can be deployed separately, and a cross-cutting Global module. Let’s have a look at CUBA’s **Global** and **Core** modules and their contents in details.

### Global Module

#### Entity Model

Entity model in a CUBA application should be familiar to any developer who worked with JPA-compatible ORM framework and Spring. It is just classes annotated with @Table, @Entity etc. and registered in the persistence.xml file.

In the entity model for the Pet Clinic application you can reuse the code from the Spring version, but you need to remember a couple of things:

1.  CUBA <a href="https://doc.cuba-platform.com/manual-latest/manual.html#qs_create_project" target="_blank">introduces</a> a “namespace” for every application <a href="https://doc.cuba-platform.com/manual-latest/app_components.html" target="_blank">component</a> created with this platform to prevent names clash between different components. That’s why there is a “petclinic$” prefix for every entity name.
2.  It is recommended to use a @NamePattern annotation for entities to get a meaningful instance representation in UI.

The question is - what CUBA gives us apart from prefixes and declarative entity “stringified” representation? Additional features include:

1.  Base classes that support ID generation functionality: from Integer IDs to UUIDs..
2.  A set of helpful (but optional) interfaces:
    *   Versioned - to support entity versions.
    *   SoftDelete - to support “soft”, a.k.a “logical” delete for an entity.
    *   Updatable - adds fields for entity update logging.
    *   Creatable - adds fields for entity creation logging.  
        You can read more about these interfaces in the <a href="https://doc.cuba-platform.com/manual-latest/data_model.html" target="_blank">documentation</a>.
3.  Database schema creation and update scripts can be generated by CUBA Studio automatically.

_During the application development I just copied existing entities models from the Spring version and added CUBA-specific features mentioned above, deleting BaseEntity class from the reference version of the application._

#### Views

CUBA’s “Views” concept may be confusing, but it is quite easy to explain. A View is a declarative way to specify which data (attributes and nested instances/collections) should be extracted.

Let’s assume that you need to fetch owners and their pets or vets with their specialities - for displaying dependent entities along with “parent” data on the same UI screen. In case of pure Spring implementation you need to define JPA joins...

    @Query("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id")
    public Owner findById(@Param("id") int id);

… or define proper EAGER/LAZY fetch types to get dependent collections for an entity within transaction context.

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), 
    inverseJoinColumns = @JoinColumn(name = "specialty_id"))
    private Set specialties;

In CUBA version you can use EntityManager and JPQL or views and DataManager:

1\. Define a view that specifies what we want to extract:
```java
<view class="com.haulmont.petclinic.entity.Vet"
	extends="_minimal"
	name="vet-specialities-view">
	<property name="specialities"
		view="_minimal">
	</property>
</view>
```

2\. Use <a href="https://doc.cuba-platform.com/manual-6.8/dataManager.html" target="_blank">DataManager</a> bean to get this data

    public Collection findAll() {
    	return dataManager.load(Vet.class)
    		.query("select v from cubapetclinic$Vet v")
    		.view("vet-specialities-view")
    		.list();
    }

You can create different views for different tasks choosing which attributes you want to get, whether or not to fetch collections and define how deep your object tree will be. There is a great <a href="https://www.road-to-cuba-and-beyond.com/views-the-uncharted-mystery/" target="_blank">post</a> about views in Mario David’s <a href="https://www.road-to-cuba-and-beyond.com/" target="_blank">blog</a>.

In the Pet Clinic application we defined six views for different cases. Those views are used mostly in UI forms and one of them - for fetching data in the service, the code snippet is shown above.

#### Services Interfaces

Since Global module is a cross-cutting module of a CUBA-based application, you should define service interfaces in it to be able to use services in other modules by using Spring injections. All you need to do is to register services in “web-spring.xml” file in Web module. The CUBA platform creates proxies in application modules for transparent entities serialization and deserialization using this Spring config XML file. This feature lets us call services implemented in Core from other modules even in case of distributed deploy with a minimum of additional efforts.

_So in terms of Entity model development with CUBA it is all the same as in pure Spring, but you shouldn’t care about ID generation and retrieval entity’s ID after insert and don’t need to create extra code for entity versioning, soft delete and entity change log. Also you can save some time on creating views instead of JPA joins._

### Core Module

Core module contains service implementations for interfaces declared in Global module. Every service in CUBA application is usually annotated with @Service, but you can use all available Spring annotations to deal with beans. There are a couple of limitations due to CUBA’s architecture though:

*   You need to annotate your service with @Service if you want it to be exposed in Web module.
*   It is recommended to give a name for your service to avoid bean clash from different add-ons.

Other than that, your Core module codebase is a “pure” Spring-based backend application. You can fetch data from data store(s), invoke 3rd party web services, etc. in the same way as you used to. The only significant difference is interaction with database.

#### Entity Manager and DataManager

The platform uses its own <a href="https://doc.cuba-platform.com/manual-latest/entityManager.html" target="_blank">EntityManager</a> that delegates part of its functionality to an actual javax.persistence.EntityManager instance. CUBA’s EntityManager provides mostly low-level entity operations and does not support security features. In most cases it is recommended to use <a href="https://doc.cuba-platform.com/manual-latest/dataManager.html" target="_blank">DataManager</a> that gives extra functionality:

1.  Row-level and attribute-level security support.
2.  CUBA’s entity views usage for fetching data.
3.  <a href="https://doc.cuba-platform.com/manual-latest/dynamic_attributes.html" target="_blank">Dynamic attribures</a>.

More about DataManager and EntityManager you can find in the <a href="https://doc.cuba-platform.com/manual-latest/dm_vs_em.html" target="_blank">documentation</a>. Please note that you don’t need to use those beans directly in GUI - there are <a href="https://doc.cuba-platform.com/manual-latest/datasources.html" target="_blank">Datasources</a> for this.

_Talking about PetClinic - I (almost) didn’t write a lot of code in the Core module since there was no complex business logic there._

### Features from Spring Pet Clinic in CUBA

In the previous section there was a list of extra functionality in the Spring-based Pet Clinic application, the same features are available in CUBA.

#### Caching

CUBA provides entity and query caches as built-in features. Those caches are described in details in <a href="https://doc.cuba-platform.com/manual-6.8/entity_cache.html" tarhet="_blank">documentation</a> and should be considered first since they support all platform features like distributed deploy. In addition to this, you can enable caching by using Spring’s @Cacheable and enable caching as described in Spring <a href="https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-caching" target="_blank">documentation</a>.

#### Validator

CUBA uses <a href="https://doc.cuba-platform.com/manual-latest/bean_validation_running.html">BeanValidation</a> as a standard validation engine. If built-in validation is not enough, you can define <a href="https://doc.cuba-platform.com/manual-latest/bean_validation_constraints.html#bean_validation_custom_constraints" target="_blank">custom validation code</a>. And there is always an option to verify data in the UI by defining Validator class as described <a href="https://doc.cuba-platform.com/manual-latest/gui_validator.html" target="_blank">here</a>.

#### Formatter

CUBA platform provides several <a href="https://doc.cuba-platform.com/manual-latest/gui_formatter.html" target="_blank">formatters</a> for GUI components, but you can <a href="https://doc.cuba-platform.com/manual-6.8/gui_formatter.html" target="_blank">define your own formatter</a> apart from standard formatters. For default entity representation @NamePattern annotation is used.

#### I18n

CUBA platform supports <a href="https://doc.cuba-platform.com/manual-6.8/localization.html" target="_blank">internationalization</a> in the same way as other java applications: by using message.properties files, so nothing new here.

#### Transaction management

CUBA platform provides the following <a href="https: doc.cuba-platform.com="" manual-latest="" transactions.html"="">transaction management options:</ahref="https:>

*   Familiar Spring’s @Transactional annotation
*   CUBA’s <a href="https://doc.cuba-platform.com/manual-6.8/persistence.html" target="_blank">Persistent</a> interface if you need a fine-grained transaction management in some complex cases.

_When I was developing the Pet Clinic, I thought about transactions only once - during development of the form that allowed editing owners, pets and adding visits on the same screen. I needed to understand when to commit a transaction and refresh a UI to display data in a consistent way._  

## Pet Clinic in a few hours. Really

I was able to create an application with the same functionality as Spring’s Pet Clinic with a “standard” CUBA UI in less than a day. I wouldn’t say I’m an expert in CUBA (it’s been just several weeks since I started), but I have a long history of using Spring. Let’s have a look at a CUBA-based app with Spring architecture in mind:  
**Domain Model** - entities in **Global** module. Creating an entity model was a well-known routine. Kudos to BaseIntegerIdEntity class for saving some time on ID generation.  
**Repository Layer** - I didn’t need repositories. Not even an interface. I just created some views using CUBA Studio GUI. With this tool I didn’t need to write XML in configs.  
**Service Layer** - In our application we have only two services to export vets in JSON and XML format with cacheable result. I put interfaces to **Global** and implementations to **Core** as per documentation. Then it was just a “normal” development apart from reading about DataManager a bit to get familiar with its API.  
**Controllers Layer** - The CUBA Pet Clinic contains only one custom REST controller for JSON and XML feed in **Web** module. No surprises here, it was just a Spring controller with familiar annotations.  
**Application GUI** - creating “standard” CRUD forms with CUBA Studio was a breeze.  
I didn’t think about passing entities to web UI and form submission - no controllers and repositories. CUBA provided me a proper grid and a component for data filtering, so no more parsing query strings and fuss with Pageable. I spent most of the time implementing proper UI flow, renderers and applying styles.

My personal experience is shown in the table:

<table>

<tbody>

<tr>

<td></td>

<td><b>Easy to Understand and Develop</b></td>

<td><b>Need to Read Documentation</b></td>

</tr>

<tr>

<td><b>Entities</b></td>

<td>Entity Modelling  
DB Creation Scripts  
Standard base classes</td>

<td><a href="https://doc.cuba-platform.com/manual-latest/data_model.html">Additional features for soft delete etc.</a></td>

</tr>

<tr>

<td><b>Repositories</b></td>

<td>EntityManager  
Views</td>

<td><a href="https://doc.cuba-platform.com/manual-latest/dataManager.html">DataManager</a></td>

</tr>

<tr>

<td><b>Services</b></td>

<td>Beans management  
Transaction management  
Security and user management</td>

<td><a href="https://doc.cuba-platform.com/manual-latest/persistence.html">Persistent interface</a></td>

</tr>

<tr>

<td><b>Controllers</b></td>

<td>Custom REST Controllers  
Request URL mapping</td>

<td><a href="https://doc.cuba-platform.com/restapi-7.1/#rest_api_v2_services_config">Service methods publishing</a></td>

</tr>

<tr>

<td><b>UI</b></td>

<td>Standard forms</td>

<td><a href="https://doc.cuba-platform.com/manual-latest/own_components.html">UI customization</a></td>

</tr>

</tbody>

</table>

Obviously Pet Clinic application does not use all CUBA features, the full list can be found on the <a href="https://www.cuba-platform.com/framework-features" target="_blank">site</a> where you will see other common tasks that can be solved by the platform.

_My personal opinion - CUBA simplifies back-end implementation and doing great if you use its “standard” GUI. Even if you need a fancy UI, CUBA will save your time on back-end development for sure._

### So many pros! What about cons?

Well, there are some things I would like to mention in this section. These things are not game changing, however I found them quite unwanted at first steps of getting familiar with CUBA.

*   In the introduction section it was told that CUBA platform comes with its own IDE that simplifies project creation and management. Sometimes switching between Studio and your IDE might be a bit irritating, but we’re redeveloping it now, so Studio will transform into IDEA’s plugin soon.
*   In CUBA we use a bit more XML config files than in typical Spring Boot application because of more services provided by the platform.
*   There are no “friendly” URLs for each of the application’s UI form yet. You can access screens directly using <a href="https://doc.cuba-platform.com/manual-latest/link_to_screen.html" target="_blank">screen links</a>, but they are not very “human-readable”.
*   You have to deal with CUBA’s DataManager and EntityManager and learn their API rather than Spring JPA or JDBC (but can still use them if needed).
*   You will achieve the best development performance with CUBA when using relational databases. As for NoSQL - CUBA performs as well as Spring does, it is the same amount of coding work.

## Conclusion

If you have a task for implementing data-centric intranet application that uses RDBMS as a data storage you may want to try CUBA platform as a basis because:

1.  CUBA is transparent. Source code is available and you can debug everything.
2.  CUBA is flexible (up to some limit). You can inherit and inject your own beans instead of standard CUBA beans, publish custom REST API and use your own UI framework to interact with user.
3.  CUBA is Spring. 80% of your back end code will be a pure Spring application.
4.  You can start fast. An application is ready for use right after first entity and UI screen creation.
5.  A lot of routine work is done for you.

So by using CUBA you will save some time on routine tasks for the real fun dealing with complex business-related algorithms and non-trivial integrations with other applications.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Web application security]]></title>
            <link>https://www.jmix.io/cuba-blog/web-application-security</link>
            <guid>https://www.jmix.io/cuba-blog/web-application-security</guid>
            <pubDate>Wed, 16 May 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/e28c5989161141c98f85c0efe40a164d.jpeg">How secure a web application should be? Well, for many of us, web-developers, the question doesn't make much sense. "An application must be as secure, as it is possible. The more secure it is, the better". But it is not a definite answer. It doesn't help to form a security policy of a project. Moreover, sticking to just this single directive ("The more secure it is, the better") may prove to be an ill service. Why? That's what I'm going to discuss in this article.]]></description>
            <content:encoded><![CDATA[How secure a web application should be? Well, for many of us, web-developers, the question doesn't make much sense. "An application must be as secure, as it is possible. The more secure it is, the better". But it is not a definite answer. It doesn't help to form a security policy of a project. Moreover, sticking to just this single directive ("The more secure it is, the better") may prove to be an ill service. Why? That's what I'm going to discuss in this article.

## Security often makes usability worse

Excessive security checks certainly make an application more annoying. Mostly it's true for 2 parts of an application: authentication and forgotten password functionality.

Multistage authentication that includes SMS verification and additional protective fields, apart from password, makes a user experience a little more secure, but less enjoyable. And the user certainly won't appreciate your attempts to make his experience more secure, if all your service does is allowing to exchange funny pictures with other users.

Best security practices advise to show as little info as possible in cases of authentication errors, to prevent an intruder from collecting a list of users. According to this advice, if a user went through 33 stages of authentication and made a typo in one field, the best solution would be to show a message like: "Sorry, something went wrong. Please, try again". Gratitude to developers and sincere admiration for their efforts to make a user experience as safe as possible are the emotions that the user is unlikely to experience in that case.

You must fully realize, in which case a user experience gets worse, and decide if this is acceptable in your specific situation.

## Security makes applications harder to develop and support

The more defense mechanisms an application has, the more complicated it is. Time required for creating some parts of the application might increase by several times to include a minor security improvement.

Much effort can be spent just on making a life of intruders more frustrating, and not on fixing actual security problems. For example, the project may choose to obfuscate method names and parameters names in its REST API.

Frequently, developers spend much time to prevent an intruder from harvesting a list of usernames through a login form, a registration form and a forgotten password form.

There are approaches, when an app marks a user as an intruder, but doesn't reveal it. All user requests will be simply ignored.

If a multistage authentication process includes a secret question, that is unique for every user, then we still can show a question for a username that doesn't exist in our entries. Moreover, the application can store in a session or in a db this username and the shown question to consistently ask for the same information.

There are plenty of other ways how to confuse an intruder. But surely they all require time to be implemented. And this logic might be quite intricate even for its authors, even if it's written well and has commentaries. But the most important thing is that it doesn't actually fix any security issue, it just prevents from finding such issues.

It's not always that simple to separate "A well-designed and truly safe functionality" from "Wild mind games with an imaginary hacker". Especially because a fine edge between these two extremes is not absolute and greatly depend on how much your application is attractive to potential hackers.

## Security makes applications harder to test

All our security logic must be tested. Unit tests, integration tests or manual testing - we should choose an appropriate approach for every single security mechanism we have.

We can't just give up testing our defense logic, because bugs tend to appear in our work. And even if we were able to write everything correctly in the first place, there is always a chance that bugs will be added during maintenance, support and refactoring. Nobody starts a project by writing a legacy code. The code becomes legacy over time.

It's not sensible to thoroughly test all business logic, but at the same time to assume that our security mechanisms are perfect, absolute and error-free.

If security logic will be tested manually, then there is a question of how often must it be done. If our application is more or less complicated, then there can be dozens, if not hundreds, places where broken authentication can be. For instance, if in some request some ID parameter is changed, the server returns an information that must not be accessible to us. Checking every similar possible case is a lot of work. Should we check it before every major release? Should we assign an individual person for this task? Or should we even have a whole team for this?

These questions are important. Broken authentication can be easily introduced into the project. We must be vigilant while making any tiny change in our model and adding new REST method. There is no simple and universal answer to this problem. But there are approaches that allow dealing with the problem consistently throughout a project. For instance, we, in CUBA platform, use  [roles](https://doc.cuba-platform.com/manual-6.8/roles.html) and [access groups](https://doc.cuba-platform.com/manual-6.8/groups.html). They allow configuring which entities are accessible to which users. There is still some work to configure these rules, but the rules themselves are uniform and consistent.

Apart from broken authentication there are dozens of security problems that should be tested. And implementing a new mechanism or logic, we must consider how it will be tested. Things that are not tested tend to break over time. And we get not only problems with our security, but also a false confidence that everything is ok.

There are 2 types of security mechanisms that cause the most trouble: mechanisms that work only on prod environment and mechanisms that represent a 2nd (3d, 4th) layer of security.

**Defense mechanisms that work only on production.** Let's assume that there is a session token cookie, which must have a "secure" flag. But if we use HTTP everywhere in our test environment that means that there are separated configurations for testing and production. And therefore we test not exactly the product that will be released. During migrations and various changes the "secure" flag can be lost. And we won't even notice that. How do we deal with the problem? Should we introduce one more environment that will be used as pre-production? If so, then what part of our functionality should be tested on this environment?

**Multilayered defense mechanisms.** People, experienced in security issues, tend to create a security logic that can be tested only when other security mechanisms are turned off. It actually makes sense. Even if an intruder manages to find a vulnerability in the first layer of our security barrier, he will be stuck on the second. But how it is supposed to be tested? A typical example of this approach is the use of different db users for different users of the app. Even if our REST API contains broken authentication, the hacker won't be able to edit or delete any info, because the db user doesn't have permissions for these actions. But evidently such configurations tend to outdate and break, if they are not maintained and tested properly.

## Many security mechanisms make our applications less secure

The more defense checks we have, the more complicated an app is. The more complicated the app is, the higher probability of making a mistake. The higher probability of making a mistake, the less secure our application is.

Once again let's consider a login form. It's quite simple to implement login form with 2 fields: username and password. All we need to do is to check if there is a user in the system with a provided name and if a password is entered correctly. Well, it's also advisable to check that our application doesn't reveal in which field a mistake was made, to prevent an intruder from harvesting user names, although this practice can be sacrificed for some applications to make a more pleasant user experience. Anyway, we also have to implement some kind of brute-force defense mechanism. That, of course, should not contain a fail-open vulnerability. It's also a good idea not to reveal to the intruder that we know that he is an intruder. We can just ignore his requests. Let him think that he is continuing to hack us. Another thing to check is that we don't log user passwords. Well, actually there is another bunch of less important things to consider. All in all, a standard login form is a piece of cake, isn't it?

Multistage authentication is a completely different thing. Some kind of token can be sent to the e-mail address or via SMS. Or there can be several steps, involving entering more and more information. This all is quite complicated. In theory, this approach should diminish the possibility of a user account being hacked. And if the functionality is implemented properly, then it's the case. There is still a possibility to be hacked (nor SMS, nor e-mail message, nor anything else will give us 100% guarantee), but by these means it reduces. But the authentication logic that already was quite complex, becomes much more complicated. And the probability to make a mistake increases. And existence of a single bug will prove our new model to be less secure, than it was while it was just a simple form with 2 fields.

Moreover, intrusive and inconvenient security measures may force users to store their sensitive data less secure. For example, if in a corporate network there is requirement to change password monthly, then users, that don't understand such annoying measures, might start to write their passwords on stickers and put them on their screens. "It's totally a fault of users, if they commit such follies", you can object. Well, maybe. But it's definitely your problem too. At the end of the day, isn't the satisfaction of users' needs is our final goal as developers?

## Got it. So what are you suggesting?

I suggest deciding from the start, how far are we ready to go to obstruct an intruder. Are we ready to optimize our login form so, that the response time on login requests won't reveal if a user with such a name exists or not? Are we ready to implement checks so reliable, that even a close friend of a victim sitting from his/her cellphone is not able to access an application? Are we ready to complicate development by several times, inflate the budget and sacrifice the good user experience for the sake of making a life of the intruder a little more miserable?

We can endlessly work on security, building new layers of protection, improving monitoring and user behavior analysis, impeding an obtaining of information. But we should draw a line that will separate things we must do from things we must not do. Certainly, during project evolution this line can be re-considered and moved.

In the worst case scenario, a project can spend a lot of resources on building an impenetrable defense against one type of attacks, while having an enormous security flaw in some other place.

When making a choice, if we are going to implement some security mechanism or if we are going to build another layer of security, we must consider many things:

*   How easy is it to exploit a vulnerability? Broken authentication can be exploited easily. And it doesn't require any serious technical background for it. Therefore, the problem is important and should be dealt with accordingly.
*   How critical is a vulnerability? If an intruder is able to obtain some sensitive information about other users or, even worse, can edit it, then it's a quite serious problem. If an intruder can collect ID-s of some products of our system and cannot use these ID-s for anything particular interesting, then the problem is much less severe.
*   How much more secure will an application be if we implement this feature? If we are talking about additional layers of security (for instance, checking XSS problems on an output, when we already implemented a good mechanism for input sanitization), or we are just trying to make a life of an intruder harder (for example, we try to conceal the fact that we marked him as a hacker), then the priority of these changes in not high. Maybe they may be not implemented at all.
*   How much will it take time?
*   How much will it cost?
*   How much worse will a user experience get?
*   How difficult will it be to maintain and test the feature? A common practice is never to return 403 code on attempt to access a restricted resource, and always to return 404 code. This will make it harder to collect identifiers of resources. This solution, although makes it more difficult to gain information about the system, at the same time complicates testing, production error analysis. And it can even prove to be harmful to a user experience, because a user can get a confusing message that there is no such resource, although the resource exists, but for some reasons became inaccessible to the user.

Well, surely, in your specific case there may be a need in a multistage authentication mechanism. But you must fully understand in which ways it impedes the development and makes an application less enjoyable for users.

## You are justifying a negligent approach towards security

Well, I am not. There are certainly security-sensitive applications, which will gain from additional security measures. Even if these measures increase expenses and destroy user experience.

And, of course, there are a number of vulnerabilities that should not appear in any application, no matter how small it is. CSRF is a typical example of such a vulnerability. Defending against it doesn't make user experience worse and doesn't cost a lot. Many server-side frameworks (such as Spring MVC) and front-end frameworks (such as Angular) allow supporting CSRF-tokens out-of-the-box. Furthermore, with Spring MVC we can quickly add any required security header: Access-Control-*header, Content-Security-Policy, etc.

Broken authentication, XSS, SQL injection and several other vulnerabilities are not permitted to have in our applications. Defense against them is easy to grasp and is perfectly explained in a great range of books and articles. We also can add to this list passing a sensitive info inside URL parameters, storing weakly hashed passwords and other bad security practices.

In the best possible way, there should be a manifest in a project, which describes a security policy of the project and answers such questions as:

*   What security practices are we following?
*   What is our password policy?
*   What and how often do we test?
*   etc.

This manifesto will be different for different projects. If a program has an insertion of user input into OS command, the security policy must contain an explanation of how to do it safely. If the project can upload files (such as avatars) to a server, the security policy must enumerate possible security problems and how to deal with them.

Certainly, it's not an easy task to create and support such a manifesto. But expecting that each member of a team (including QA and support) remembers and sticks to every security practice he must to, is kind of naive. Moreover, there is a problem that for many vulnerabilities there are several ways to handle them. And if there is no definite policy on the matter, then it can occur that in some places developers use one practice (for example, they validate input information) and in other places they do something completely different (for example, they sanitize an output). Even if the code is good and pure, it's still inconsistent. And inconsistency is a perfect ground for bugs, support problems and false expectations.

For small commands with a constant technical leader code review may be enough to avoid aforementioned problems, even if there is no manifesto.

Summary:

*   Working on security we should consider how our application is security sensitive. Bank applications and applications for sharing funny stories require different approaches.
*   Working on security we should consider how harmful it will be for a user experience.
*   Working on security we should consider how much it will complicate the code and make maintenance more difficult.
*   Security mechanisms should be tested.
*   It's advisable to teach team members how to deal with security issues and/or perform a thorough code review for every commit in a project.
*   There are certain vulnerabilities that have to be eliminated for every application: XSS, XSRF, injections (including SQL injection), broken authentication, etc.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Marketplace Goes Live!]]></title>
            <link>https://www.jmix.io/cuba-blog/marketplace-goes-live</link>
            <guid>https://www.jmix.io/cuba-blog/marketplace-goes-live</guid>
            <pubDate>Wed, 11 Apr 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/a5f961a7960a4ceaaa319c4c27d20355.png">These days we are starting the Marketplace - an all-new ecosystem around CUBA platform. From now and on developers can pick & choose new features from an [add-on catalog on our website](https://www.jmix.io/cuba-platform/marketplace/) to enrich their apps with no hassle. The catalog consists of the add-ons which were developed either by Haulmont or by CUBA community. Both free and paid components can be found there.]]></description>
            <content:encoded><![CDATA[These days we are starting the Marketplace - an all-new ecosystem around CUBA platform. From now and on developers can pick & choose new features from an [add-on catalog on our website](https://www.jmix.io/cuba-platform/marketplace/) to enrich their apps with no hassle. The catalog consists of the add-ons which were developed either by Haulmont or by CUBA community. Both free and paid components can be found there.

We call you for participation and will be grateful if you find time and submit your free or paid components to the Marketplace. Please, fill out the [form](https://www.cuba-platform.com/marketplace/suggest-component) if you decide to do so.

We are doing our best in keeping your expectations fulfilled. Marketplace is an important milestone we have passed following our [public roadmap](https://www.cuba-platform.com/blog/roadmap-2018). If you have any ideas on how to improve its content or appearance, please, post a message in the dedicated topic on our forum.

To keep you informed, we are going to upload the following add-ons later this year:

*   WebDAV
*   LDAP
*   IMAP
*   Rich Search

Looking forward to see _your_ add-on in the catalog!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Platform Roadmap 2018]]></title>
            <link>https://www.jmix.io/cuba-blog/roadmap-2018</link>
            <guid>https://www.jmix.io/cuba-blog/roadmap-2018</guid>
            <pubDate>Tue, 06 Mar 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/2778a5a134d54913b1c2a8ac9d27da69.jpg">As promised in my last post, we would like to announce our development plan for the year ahead. Of course, it contains only major features, with 100s of smaller improvements to come as well.]]></description>
            <content:encoded><![CDATA[DISCLAIMER: This plan is not set in stone, and we will surely deliver things on top of it, as well as some features may slip or even fall out on the way. However, in general, we intend to stick to it, so it can serve as a good indication of CUBA Platform development direction for the community.

TEASER: CUBA Studio will be built into IntelliJ IDEA.

So here we go!

## Quarter 1

Most of the quarter has already passed, so retrospectively we have released Electron-based [Studio Standalone Edition](https://www.cuba-platform.com/discuss/t/cuba-studio-se-a-desktop-application-based-on-electron/2914), as well as [Release 6.8](http://files.cuba-platform.com/cuba/release-notes/6.8/).

In the remaining month, we intend to roll out the Marketplace to the website. The Marketplace will be a common place to share Addons, developed by us or by any member of the community. This is an important milestone, giving a start to a new ecosystem around CUBA Platform, so developers can pick & choose what they need and plug in new features in their apps with minimal hassle.

Technically, most of the Addons will be available as [application components](https://doc.cuba-platform.com/manual-latest/app_components.html), so adding them to your project will be as easy as copy-pasting Maven coordinates in Studio.

For the start, we will bring together the Addons already released and available on GitHub:

*   [Drag&Drop](https://github.com/cuba-platform/cuba-dnd) - drag & drop support for the Generic UI
*   [JavaMelody](https://github.com/cuba-platform/cuba-jm) - integration with the popular monitoring tool
*   [ZooKeeper](https://github.com/cuba-platform/cuba-zk) - dynamic discovery of middleware servers
*   [Localizations](https://github.com/cuba-platform/translations) for German, Spanish, Danish, Dutch, Portuguese, Simplified Chinese and Romanian

We also know a few community members who are already willing to contribute their components - so the list should be growing!

## Quarter 2

Studio will get the following improvements:

*   Multi-windows support in the SE version
*   Support for “thin” app components in Studio (e.g. without Core or Web modules)

New Addons will be published:

*   WebDAV - support for the powerful WebDAV remote documents storage protocol
*   LDAP - advanced integration with LDAP
*   IMAP - an Addon, which reads and displays mail over the IMAP protocol, and throws events which can be handled in your business logic
*   Rich Search - extendable full-text search over menu items and screens

Polymer UI

*   TypeScript support

## Quarter 3

The Beta versions of Platform and Studio 7 will bring some major changes.

### Platform 7 Beta

The main focus is the upgrade of the stack - we migrate to Vaadin 8 and make the Platform compatible with Java 9\. For the already running projects this means that we do the hard work, so you don’t have to :) Of course, migrating to a new major version of the platform can not be seamless, but it will be way easier compared to upgrading the whole stack in your project manually.

Another notable change is the new UI data layer and API. CUBA Platform will follow the trending way of event-driven architecture: new lightweight screen controllers with annotated methods for event handling will make your code clearer and easier to test. Typed API for opening screens will save from type-casting.

The new presentation data layer will replace screen datasources. This will solve many of the current issues ranging from unclear API and limited browser-editor interaction to inability to filter a nested collection.The remaining list of main changes looks as follows:

*   WebSocket communication between tiers
*   Support for URL browser history
*   Simplified creation of composite components: components, based on other components

On the Polymer UI side we will:

*   move to Polymer 3
*   introduce better support for CUBA security
*   move to vaadin-elements instead of paper-* elements (material design will be optional)

### Studio 7 Beta

Here we come to the most interesting part. Since version 7, Studio will be built in the free community version of IntelliJ IDEA as a plugin! All the current functionality, including the WYSIWYG designer, will be preserved, but Studio will now provide full power for working with code as well.

We understand that this is a big change, however, after heavy consideration, we decided this is the way to go. We also have good answers for those of you using Eclipse or NetBeans.

First of all, this change will mean that we can finally deliver 100% smooth user experience for CUBA developers. No more flicking between Studio and an IDE. Next, the code management capabilities of IntelliJ open up enormous opportunities to automate and streamline CUBA-specific tasks and code generation even further. As a little example, this means we will be able to provide full support for Kotlin.

Next, IntelliJ IDEA is the most popular Java IDE in the world, and in our opinion the most productive as well. The fact that Eclipse <u>lost another 8%</u> of its market share in 2017 only proves this.

Finally, the community version of IntelliJ is free, so this change will not have any economic impact on Studio users. We hope that Eclipse users will try and find the migration easy... and worth doing! If not - we have a CLI coming to rescue (see below)!

What many developers love about CUBA Studio is the easy start. We do not want to compromise this, so we intend to create a customized version of IntelliJ, with CUBA Studio plugin and starter wizard. This version will be available for download from our website, just like Studio now.

### Development CLI

As you know, CUBA Platform is open source, while CUBA Studio is a commercial tool. At the moment, the recommended way of starting a free project is using the free version of CUBA Studio and switching to an IDE when its 10 entities limit is hit.

So while in practice this approach is totally fine, it does not feel like 100% open source. It is not easy just to get the framework from GitHub and start your project. And Studio merging into IntelliJ brings even more tool locking.

To resolve this, we will be launching an open source, lightweight and IDE-independent CLI (command line interface) tool to scaffold project infrastructure, entities, CRUD screens, and more. The tool should also allow plugging in your own commands.

Now we give developers a clear choice to cater for both philosophies:

*   free, fully open-source, IDE-independent Platform+CLI on one hand;
*   and the convenience of visual development in Studio on the other, becoming even more productive with merging into IntelliJ IDEA.

### Addons

*   Dashboards - a dynamic frame which can display user-configured widgets
*   Admin Tools - a collection of tools which help deploy, maintain, and troubleshoot CUBA applications
*   Data Import - support for data import from various sources with custom mappings
*   Public registration - a component to facilitate login via social network accounts

## Quarter 4

Platform and Studio 7 become production releases.

In the everchanging landscape of Javascript frameworks, relying on just one seems to be a short-sighted strategy. So the web portal team plans to introduce support for alternative front-end clients, like React and Angular, based on a more generic core, which you can use with a front-end of your choice.

Again, like with Studio vs CLI, we believe this gives a complete choice of weapons for developers:

*   Opinionated, lightning-fast to develop Vaadin-based client for enterprise-standard UI;
*   Non-opinionated, not limiting client for solving any UI challenges with a technology of your choice.

Combining those two in your app can be very efficient, e.g. you could have a public facing portal built on whatever you like, with a functional admin UI built in no-time with a generic Vaadin-based UI. And this is exactly what we did when developing our Store.

### Addons

The main change here is the new BPM. In essence, we aim to deliver a complete integration between CUBA and the BPM engine, so most tasks can be accomplished visually without coding, or with minimal coding. This means integration with CUBA data model, UI, services, and security, including:

*   CUBA-specific stencils and the ability to create custom ones easily
*   ability to create process forms visually
*   invoking CUBA services
*   binding CUBA entities and their attributes to the process variables
*   binding process variables to CUBA window and service parameters
*   CUBA UI for logging and managing running processes and displaying user assignments

and much more!  

Other addons to be released:

*   Messengers - support for communication via popular messengers including WhatsApp, Viber, Slack and others
*   Multitenancy - an addon, simplifying the development of multi-tenant applications
*   Data drafts - prevents data loss if a user occasionally closed browser, or a web server went down.

## Summary

We are looking forward to introducing a great deal of positive improvements this year: upgrade the stack, make the framework easier to use, deliver a new level of development experience with Studio and CLI, and dramatically extend the functionality, covered by CUBA Platform, via the Addons ecosystem. We invite the community members to help us on this way via both pull requests to the framework and submitting addons to the Marketplace!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Leveraging the power of web UI for desktop front-ends]]></title>
            <link>https://www.jmix.io/cuba-blog/leveraging-the-power-of-web-ui-for-desktop-front-ends</link>
            <guid>https://www.jmix.io/cuba-blog/leveraging-the-power-of-web-ui-for-desktop-front-ends</guid>
            <pubDate>Wed, 21 Feb 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/868949fbd6844f81afcf7418b41d1e7e.png">No doubts, that web technologies and tooling for creating UIs are way more advanced than what we see in the desktop side. JavaFX is borrowing more and more CSS, but still far from being ideal; JNLP is officially deprecated in Java 9. This situation makes us think using web tech for desktop clients. So, is it achievable? And if yes, then how?]]></description>
            <content:encoded><![CDATA[#### Disclaimer

*The article uses CUBA Studio as an example of enriching a web application with useful features of a desktop application by settling it on top of the Electron framework. Later on, this experiment showed very good results. In fact the "standalone" version of the Studio went more used than the web-based. This trend naturally led CUBA Studio to become a part of an IDE. Since <a href=" https://www.cuba-platform.com/blog/whats-new-in-CUBA7/" target="_blank">CUBA 7</a>, the Studio is built into IntelliJ IDEA.*

## What is happening to Java desktop technologies

In these latter days, the most widely used Java technologies for desktop do not evolve: Swing implementation has been put on hold indefinitely, SWT simply does not deliver new features. The latest live technology is JavaFX.

The impact of web technologies is great in desktop frameworks. Even JavaFX is trending towards the web techniques, borrowing more and more features from the web world. So, JavaFX supports a subset of CSS features, accompanying it with their own properties.

However, this all is far away from what the web offers for UI. Another essential aspect is tooling. Have you seen anything in any way similar to developer tools coming along with all the popular web browsers for desktop UI design? Finally, the fact that JNLP goes deprecated in Java 9, it certainly doesn't add points to desktops.

But then, why does desktop stay afloat? There are a few very important things that are poorly covered by a web approach:

*   Offline mode
*   Advanced integration with peripheral devices
*   Local data/file processing

Partially, these problems are being solved using new web standards, such as Service Worker, but it would be great if we could implement a technology that brings web UI development technologies and tooling to our desktop Java applications.

## What does Electron.js have to do with it

Electron is a well-known technology for desktop applications from the JavaScript world. It is a technology behind GitHub’s Atom editor. Atom was the first widely known desktop application built with HTML, JavaScript, CSS, and Node.js integration.

Electron is an open-source framework that allows using web technologies for the development of desktop GUI applications. You can use front- and back-end technologies originally developed for web applications: JS for the backend and HTML/CSS/JS for the frontend. You might be surprised, but it is <a href="https://electronjs.org/apps" target="_blank">widely used</a> not only for development tools, for instance, Slack and Skype are built on top of Electron.js.

In a nutshell, Electron consists of two main components: the Node.js backend plus a Chromium web browser in a single executable, as well as additional desktop integrations: native menus, notifications, tray icons, installers, etc.

In the <a href="https://vaadin.com/blog/desktop-uis-will-stay-alive-thanks-to-web-technologies" target="_blank">previous blog post</a> I’ve told you how to employ Electron.js to convert existing Vaadin-based web applications into full-featured desktop apps.

In this article I’ll show you how do we use it for our development tool CUBA Studio and how to improve this approach to make it suitable for business applications.

## How do we use it for CUBA Studio

As you know, CUBA Studio is an enterprise application development tool for applications based on CUBA Platform. With Studio, you can easily develop typical enterprise applications such as CRM, ERP, ECM and other business-oriented systems.

We have used Vaadin Framework for both CUBA Studio and CUBA Platform and reused a lot of UI components and technical solutions between them. Since the first release CUBA Studio has been a web application that runs locally but shows the UI inside of a web browser.

This year we <a href="https://www.cuba-platform.com/discuss/t/cuba-studio-se-a-desktop-application-based-on-electron/2914" target="_blank">introduced</a> the new version of CUBA Studio that uses Electron to bring better UX for our users. It enables developers to use CUBA Studio as an independent Desktop application without a web browser. We can use all the advantages of an operating system, such as the taskbar, fast switching between applications with shortcuts and shutdown of the application on window close.

![text]({{strapiUrl}}/uploads/ee06bec6373147b6a98c72b3bf6d2c90.png)

And what makes me so happy is that we bundled our existing Java code without any changes! Well, almost without changes, of course, we improved a couple of things.

With this technology we delivered a lot of game-changing features:

*   Desktop Integration - taskbar, window switching, shutdown on close.
*   Controlled version of the browser, thus the application will not be broken in case of an update of Chrome. And more importantly, the same version of a UI engine we tested before release.
*   Smooth automatic updates

In the next version, we are planning to introduce new features:

*   Multi windows support
*   Desktop notifications on build/deploy events

Multi windows support <a href="https://youtrack.cuba-platform.com/issue/STUDIO-3944" target="_blank">is already implemented</a>, and you can try it in our <a href="https://www.cuba-platform.com/discuss/t/cuba-studio-nightly-builds/2904" target="_blank">nightly builds</a>.

These features are available since we are no longer limited by the web browser.

How it actually works in case of CUBA Studio? There are several technical details that make it possible to run CUBA Studio inside of Electron.js:

*   CUBA Studio consists of Jetty servlet container and Vaadin-based web application. Jetty is a small yet powerful servlet container that can be easily embedded. We use the same embedding approach in our <a href="https://doc.cuba-platform.com/manual-latest/uberjar_deployment.html" target="_balnk">UberJAR deployment</a>.
*   The whole app is packaged as a self-containing application that can be run without deployment to a standalone web server. Usually, we start it with double click on the icon or as a single command from a console.
*   We have prepared a special JavaScript runner - studio.js that is used by Electron.js as the entry point of CUBA Studio application. You can even find it inside of the CUBA Studio installation directory and take a look at the actual JS code, it is located under /CUBA Studio SE/resources/app/.

The process is as follows:

1.  When users click on the application icon, Electron.js binary is starting.
2.  Then Electron.js loads and runs studio.js script.
3.  The runner script finds a free network port and starts java.exe child process of CUBA Studio application. It is the same application as before, with a number of small improvements, that allows us to improve such an integration.
4.  When CUBA Studio process has started the runner script loads the web page of it inside of the Electron.js window - Chromium browser window.
5.  That’s it! CUBA Studio is up and running!

The reverse process is the application shutdown: the runner script performs the smooth shutdown of the Java process when a user closes the last application window.

We have slightly improved this with two-way WebSocket connection (instead of AJAX) that enables us to speed up local network communication up to just 1ms per request. If you want to try this approach for your Vaadin-based app I’d recommend that you take a look at the <a href="https://github.com/cuba-labs/java-electron-tutorial" target="_blank">complete tutorial on Github</a>.

## Benefits of the Hybrid Approach for enterprise apps

It is a really cool approach for a development tool, but how about something for real life? It looks like kind of “hipster” way. Let’s talk about the benefits for business apps:

*   We have full control on the entire development stack: from the underlying web browser to our applications.
*   We still have full access to the Desktop machine: hardware, file system, installation, notifications and integration with the operating system.
*   We can use JS/CSS to develop UI widgets, at the same time employing Java for business logic.
*   We can reuse existing JS/CSS libraries and approaches.
*   We can even bundle our existing CUBA application for desktop usage!

The most important point is the latest - ability to reuse existing code and business logic on desktop without additional development. We clearly understand that it will require additional work, but still, a lot of business logic can be effectively reused!

## Experimental replacement for Swing-based desktop client

Since the first public release of the platform we provide two different UI technologies for applications: Vaadin-based Web Client and Swing-based Desktop Client. Implementation of the generic user interfaces enables you to write code that works in both clients automatically, of course, with the corresponding limitations.

Desktop Client was initially developed in 2011 on the basis of Java Swing because there were no stable and viable UI technologies for Java desktop except it. But things are changing.

Today, we are facing a lot of new requirements for Desktop UI: responsiveness, animations, and integration with network services and cloud providers, such as Google. Broadly speaking, applications are moving towards web UI technologies, and we cannot ignore this movement.

Seeing all these new challenges we have decided to do research on Electron.js and web UIs not only in CUBA Studio but also for the CUBA-based applications.

In the <a href="https://github.com/cuba-labs/cuba-electron-demo" target="_blank">sample project</a> you will find the application with the additional module: **electron**.

It contains only one required file - <a href="https://github.com/cuba-labs/cuba-electron-demo/blob/master/modules/electron/src/main.js" target="_blank">main.js</a>. It is pretty much the same script runner as in CUBA Studio. The script starts Java process using **child_process** module of Node.js:

    serverProcess = require('child_process')
       .spawn('java', ['-jar', 'app.jar'],
           {
               cwd: app.getAppPath()
           });

Only 100 lines of JavaScript, and we can start our web application as desktop?! Not that fast. We have to prepare our application first:

1.  Build web client as a self-contained application using <a href="https://doc.cuba-platform.com/manual-latest/uberjar_deployment.html" target="_blank">Uber JAR technology</a>

See <a href="https://github.com/cuba-labs/cuba-electron-demo/blob/master/build.gradle" target="_blank">build.gradle</a> file:

    task buildUberJar(type: CubaUberJarBuilding) {
       webPort = 30550 // use non-standard port for electron app
       corePort = 8080
       coreJettyEnvPath = 'modules/core/web/META-INF/jetty-env.xml'
       appProperties = ['cuba.automaticDatabaseUpdate' : true]
    }

4.  Package Electron.js application with electron-packager utility. See **buildJsWrapper** Gradle task in build.gradle
5.  Bring all the pieces together in a single directory. See **buildElectronApp** Gradle task.

After that we can start the resulting binary in ./build/electron-app/ directory. Do not forget to start the backend application from CUBA Studio, because we package only web UI to Electron.js shell.

![text]({{strapiUrl}}/uploads/73fcc3df41ed48219bb5319e9c5fe8d9.png)

It is alive! We can use all power of web UI and almost all features of CUBA Platform! I’ve spent only 4 hours to build the entire solution from scratch and it is a fantastic result!

## What is next?

There is still a lot of work to do. The following features should be implemented before this approach will become viable:

*   get rid of network for Java <> Electron.js communication
*   file downloads UI
*   multi-windows support
*   crash reporting
*   packaging and updates
*   caching and offline-mode support
*   security improvements

All these features are not that easy to implement but, at the moment, we are close enough to do that. I believe that at some point It will become our new way to build desktop clients for big enterprise solutions.

Want to see the technology in action? Try <a href="https://www.cuba-platform.com/discuss/t/cuba-studio-se-a-desktop-application-based-on-electron/2914" target="_blank">CUBA Studio SE</a>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Platform in 2017]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-in-2017</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-in-2017</guid>
            <pubDate>Thu, 15 Feb 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/6d61b619d3cb4ed1ac0dea1e75637099.png">At the dawn of 2018 it is good time again to recap what has happened with CUBA Platform over the last year. While 2016 was revolutionary for us with going open source, 2017 was more about maturity: we focused on delivering new features and offering new services to the community.]]></description>
            <content:encoded><![CDATA[At the dawn of 2018, it is a good time again to recap what has happened with CUBA Platform over the last year. While 2016 was revolutionary for us with going open source, 2017 was more about maturity: we focused on delivering new features and offering new services to the community.

## New features in Platform and Studio

Let us start from the most important part. Releases <a href="https://www.cuba-platform.com/blog/whats-new-in-cuba-platform-6-4" target="_blank">6.4</a>, <a href="https://www.cuba-platform.com/blog/whats-new-in-cuba-platform-6-5" target="_blank">6.5</a>, <a href="https://www.cuba-platform.com/blog/whats-new-in-cuba-platform-6-6" target="_blank">6.6</a> and <a href="http://files.cuba-platform.com/cuba/release-notes/6.7/" target="_blank">6.7</a> were published, each bringing hundreds of small and larger improvements. Let me list just a few of them.

### Visual Interface

**Polymer UI** offers a faster way to create front-end portals with mobile-first responsive interface. We recommend it for front-ends with complex UI requirements, keeping administrative and back-office screens developed using the standard generic user interface.

A number of new components were also added to the already rich collection of Generic UI components:

*   **Pivot Table** is a convenient tool to enable end users to analyze data;
*   **Side Menu** provides more flexibility for your app layout;
*   **DataGrid** is a faster alternative for the Table, providing more ways to display dynamic content;
*   Support for full-text search conditions in generic filter enables combining standard criteria with FTS results and gives more search power to end users.

Other components include **Predictive search, Image, Currency, Browser frame** and more.

### Core Platform

One of the key focuses here was streamlining the platform API to make it more convenient for developers. But apart of that, we delivered some useful features:

*   **Value datasources** make it easier to work with arbitrary sources of data, while **cross-datastore references** simplify combining data from different sources;
*   **Bean validation** helps to control all entity values constraints in a single place;
*   **Uber JAR** streamlines deployment of CUBA apps;
*   The new **BI add-on** provides integration of CUBA applications with Pentaho platform;
*   Integration with **ZooKeeper**, support for **load balancing** in cluster and **REST API versioning** help managing scalable/distributed deployment configurations;
*   Support for **JasperReports** templates in the Reporting add-on facilitates producing pixel-perfect reports.

### Studio

In addition to the support of the above-mentioned features like Bean Validation, Polymer UI, and value datasources, Studio got some major improvements as well.

With **screen templates** you can now automatically generate advanced screens based on built-in or even your own templates, while **screen layout controls** help to make your generic UI responsive.

And at the end of the year, we released Studio SE - a **desktop version** wrapped in Electron, eliminating the need to care about launching web server, and enabling automatic updates.

## New Add-ons

Breaking! This is a teaser for something that has not been published yet, but where we have spent a considerable amount of efforts last year. We are working on a number of new - free and commercial - add-ons, which will be extending the platform functionality and cover more typical features of an enterprise application out of the box.

Here are a few where we have already come far:

*   WebDAV - support for the popular remote documents storage protocol;
*   LDAP - advanced integration with LDAP;
*   IMAP - reads and displays mail over the IMAP protocol, and throws events which can be handled in your business logic;
*   Messengers - support for communication via popular messengers including WhatsApp, Viber, Slack and others;
*   Dashboard - a dynamic frame which can display user-configured widgets;
*   Rich Search - full-text search over menu items and screens;
*   JavaMelody - integration with a popular monitoring tool;
*   Admin Tools - a collection of tools, which help deploy, maintain and troubleshoot CUBA applications.

We will start publishing the new add-ons this spring on a marketplace, which is going live at the same time.

But we also believe that the marketplace will become a great place for the community to exchange your own brilliant pieces of software, enriching the CUBA Platform ecosystem together.

## New website and forum

In October, we’ve migrated our support forum to the cutting edge Discourse engine. This means better search and navigation, markdown support, mobile-friendliness, social features and more. With 200 topics created just over last month, we thought it is important to give the community a convenient space for communication.

New Store went live in November. Now you can not only purchase services like trainings and consulting online, but also:

*   purchase subscriptions to CUBA Studio and Premium Add-ons for periods from 3 months to 3 years, with automatic renewal;
*   get a free trial;
*   manage your subscription, consulting hours and support incidents balance from your account.

I am very pleased to note that the Store is built with CUBA Platform! We combined the new Polymer client for the public front-end with generic interface for the admin UI, and integrated the whole solution with Chargebee to manage subscriptions.

## New services

To help you get hands-on with the framework quicker, we published 10 new free <a href="https://www.cuba-platform.com/webinars" target="_blank">webinars</a> and started regular <a href="https://www.cuba-platform.com/training" target="_blank">trainings</a>.

If you need fast and professional help with your project, you can now purchase <a href="https://www.cuba-platform.com/support-options" target="_blank">consulting</a> directly from the website. If your solution is already in production - you can purchase a support agreement with a guaranteed response time for some peace of mind. And by making the basic package less beefy, we dropped the price from $8000 to just $2800 p.a.

Probably the most notable change, however, is forming the Custom Development Team. CUBA Platform was built by Haulmont, an enterprise software development house with over 300 employees currently, so of course we have been offering custom projects before. But from the last year we have a fully dedicated team, which helps CUBA Platform customers deliver their projects.

We offer two main working modes: a turnkey project delivery, where we can do everything from business analysis to post-production support; and a hybrid approach, where our experts enforce the customer team. With this approach, the customer team quickly gets the required technological expertise and at the same time brings in the business knowledge, which is crucial to delivering good software.

Just to sum it up, over the last year we launched versatile services to cover project needs at all stages!

## Wrapping up

As you can see, this has been a very productive year for the team. I hope many of those who read the blog have already benefited from the new features and services. Now we are looking forward to an even more productive year in 2018, and the roadmap is going to be published shortly. As always, your ideas are very welcome on the <a href="https://www.cuba-platform.com/discuss/c/ideas" target="_blank">forum</a>.

Stay tuned and join the community!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Classification of Development Frameworks for Enterprise Applications]]></title>
            <link>https://www.jmix.io/cuba-blog/classification-of-development-frameworks-for-enterprise-applications</link>
            <guid>https://www.jmix.io/cuba-blog/classification-of-development-frameworks-for-enterprise-applications</guid>
            <pubDate>Thu, 11 Jan 2018 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/98993ca01f8e47a78172c9f5da77998e.png">If you google "best java framework", most probably, you will stumble on this article: https://zeroturnaround.com/rebellabs/java-web-frameworks-index-by-rebellabs/, which gives a great overview about the landscape in the Java Enterprise world. However, from my point of view it lacks a very important thing - classification of the mentioned frameworks. Let's have a look at another angle at this ecosystem and go beyond the Java world.]]></description>
            <content:encoded><![CDATA[If you google "best java framework", most probably, you will stumble on <a href="https://zeroturnaround.com/rebellabs/java-web-frameworks-index-by-rebellabs/" target="_blank">this article</a>, which gives a great overview about the landscape in the Java Enterprise world. However, from my point of view it lacks a very important thing - classification of the mentioned frameworks. Let's have a look at another angle at this ecosystem and go beyond the Java world.

Picking the best framework for developing an application (or a set of frameworks), means trying to find the best trade-off between the following criteria:

1.  **Range of Applicability** - what part of the application can be developed using the framework? Do I need a set of frameworks or just one?
2.  **Development Speed** - how fast will development go?
3.  **Manageability & Flexibility** - what would be the architectural, performance and other limitations?

## Classification of Frameworks

Combining the mentioned criteria with a set of reference frameworks for each class and their outstanding characteristics in one diagram I got the following result:

![text]({{strapiUrl}}/uploads/1e3ac076c177407886953bf0243ed5de.png)

### High-level Programming Languages or "No Frameworks" Approach

This "no frameworks" approach is a degenerate case, which gives the widest Range of Applicability and highest Manageability & Flexibility you could ever get. Obviously, this is the slowest way for developing enterprise applications, as you would need to reinvent all the wheels. Normally, this level is used for building frameworks, that make development speed one step higher.

### Narrow-focused Frameworks

This class has the biggest number of representatives. All of them are intended to streamline development in a certain fairly small area by raising the level of abstraction and providing a clear API for its domain. Tying up ORM, Middleware, UI, Messaging and other kinds of frameworks is not a trivial task, however, staying within this class you have a mix of satisfactory development speed with a high level of flexibility.

### Code Generators/Aggregators

This class is intended to speed up the early stage of applications development. In fact they configure your application based on the Narrow-focused Frameworks. So, taking <a href="http://www.jhipster.tech/" target="_blank">JHipster</a> as an example, it will generate a Spring-based application with Angular-based user interface. After the startup stage there is no much value in using such frameworks.

### High-level Full-stack Frameworks

This class introduces the next abstraction level over the Narrow-focused Frameworks. So, you already have entire infrastructure to build a full-scale enterprise applications times faster. Taking <a href="https://www.cuba-platform.com/framework-features" target="_blank">CUBA Platform</a> as an example, it provides a full-stack architecture for building 3 tier applications and includes widely used common features for enterprise apps such as soft deletion, data-aware components, file storage, as well as high level modules: authentication and authorization, audit of data and others. This class is most appropriate for developing ERP-like systems, line of business applications or custom software for the corporate segment.

### Low/No Code Frameworks

At this stage you totally lose control over the code base, developing only small bits of logic in the pre-defined extension points. So, if such framework meets your requirements in terms of performance, deployment options, UI components, integrations, etc. - this would be the fastest way to configure your application. However, it might happen that one day you will not be able to step over the architectural limitations.

## Summary

Choosing the right framework of a set of frameworks for developing an enterprise application is not just about surfing the Internet looking for "top frameworks for enterprise" and picking from the top of the list. First of all, it's about solving the trade-off and finding a right mix of Range of Applicability, Development Speed and Flexibility & Manageability that meets your requirements. Once it is solved, you will be able to focus on choosing a framework itself within the right class, checking for another bunch of criteria: e.g. preferable programming language, size of community, quality of vendor support, success stories, and so on…

To sum up, I would like to provide a table with the framework classes and typical applications, they fit best.
<div class="scroll-table">
<table id="blog-758-table" border="1" cellpadding="5" class="table-bordered">
<tr>
<td>
<p><strong>Class</strong></p>
</td>
<td>
<p><strong>Typical Applications</strong></p>
</td>
</tr>
<tr>
<td>
<p>"No Frameworks" Approach</p>
</td>
<td>
<ul>
<li>Narrow-focused frameworks</li>
<li>Low level products, e.g. in-memory grids, big data processing algorithms, image recognition, etc.</li>
</ul>
</td>
</tr>
<tr>
<td>
<p>Narrow-focused Frameworks</p>
</td>
<td>
<ul>
<li>Enterprise apps with unique (uncommon) architecture</li>
<li>Microservices</li>
<li>Custom backends</li>
<li>E-commerce platforms</li>
<li>Enterprise Service Bus</li>
</ul>
</td>
</tr>
<tr>
<td>
<p>Code Generators/<wbr>Aggregators</p>
</td>
<td>
<ul>
<li>Boost at the kick-off stage for the same kind of applications as for narrow-focused frameworks</li>
</ul>
</td>
</tr>
<tr>
<td>
High-level Full-stack Frameworks
</td>
<td>
<ul>
<li>ERP applications</li>
<li>Custom BPMS applications</li>
<li>Master data management applications</li>
<li>Line of business applications</li>
<li>Custom applications with typical enterprise requirements</li>
</ul>
</td>
</tr>
<tr>
<td>
<p>Low/<wbr>No Code Frameworks</p>
</td>
<td>
<ul>
<li>Simple websites</li>
<li>Standard online stores</li>
<li>Corporate portals</li>
<li>Simple/<wbr>Typical BPMS</li>
<li>Basic CRUD applications</li>
</ul>
</td>
</tr>
</table>
</div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[New Website Is On!]]></title>
            <link>https://www.jmix.io/cuba-blog/new-website-is-on</link>
            <guid>https://www.jmix.io/cuba-blog/new-website-is-on</guid>
            <pubDate>Mon, 11 Dec 2017 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/feb01dfd6b724de59522e8b60efb4749.png">Over the last months we were working tirelessly to bring our new website into life. Starting from the last week, frequent visitors could have noticed that almost every other page has been changed to provide more clarity to the content.]]></description>
            <content:encoded><![CDATA[Over the last months we were working tirelessly to bring our new website into life. Starting from the last week, frequent visitors could have noticed that almost every other page has been changed to provide more clarity to the content.

To bring in more usability into using and buying our commercial products and services, two entirely new interfaces were added: Subscriptions Management in user account profile and a brand-new Store.

## New Store

We are happy to introduce the new Store - a one-stop shop for all CUBA Platform commercial products and services. 

![text]({{strapiUrl}}/uploads/17c6113faf9744a781282efd0013ae00.png)


### More options for CUBA Studio & Premium Addons Subscription

Based on the community requests we decided to add more flexibility and offered more options to obtain a CUBA Studio & Premium Addons Subscription. Depending on the project requirements, you can get your key for a shorter (3 or 6 months) or longer (2 or 3 years) period. We introduced the discount system depending on the period length while the default 1-year license stays unchanged and costs familiar $389\. Valuably for many clients, the invoice is now sent automatically straight after the purchase.

### Trial License directly from the Store

Together with a variety of options to obtain a commercial subscription, the Store received built-in functionality for providing trial licenses. Now you can get one right from the Store interface without the need to contact our team. The system will request to provide basic information and will charge a symbolic 1 cent to check the validity of your card.  
Note: you can only apply for a trial license once.

### Consulting services from 1 hour and 3 times more affordable Commercial Support

Our team is always happy to provide help with your project, but now our consulting services have become even more affordable. In the Store, you can purchase the required amount starting from 1 up to 80 hours and get up to 15% off from your total price.

Same applies to our SLA (Service Level Agreement), which is the most helpful at production phase. We issued a new, lighter Base Support Agreement with a much more affordable price tag. For those who need an immediate solution or want to give it a try we even propose a Single Incident option!

## Subscriptions management

For better transparency and convenience all new subscriptions can now be found and managed on your Profile page.

Multiple license keys are now grouped into a Subscription, thus all of them will have the same expiry date. By default your new subscriptions will be renewed automatically after expiration, though you can cancel the renewal at any time. You can also easily add or remove license keys from a subscription.

![text]({{strapiUrl}}/uploads/bdd0cf083de145878851dbd60000d837.png)

All your license keys are now available in your profile. Just click the View button to see your license keys with corresponding expiry dates.

![text]({{strapiUrl}}/uploads/75ff55bf99f041248b8e7d935ecaa57f.png)

Another convenient feature is the ability to see and download certificates for all training courses your team members have passed.

Note: information about previously purchased licenses or passed training courses is currently not available. We are working on adding previously purchased licenses to the profile as well, so you should be able to access them shortly.

## Powered by CUBA Platform

As you may know, we use CUBA Platform for most of our projects and we also suggest CUBA as a backend solution for websites. So, it was an obvious choice for the Store backend. As you would expect, we used Polymer client for customer-facing UI, and Vaadin for admin UI, while other parts of the website are still built on top of a classic CMS.

So the new Store acts as another good showcase of using the framework.

## Going further

We don’t stop with this update. Our further roadmap includes useful features like marketplace, referral program, enhanced account and more. Stay tuned! If you have ideas or suggestions about new website functionality, don’t hesitate to <a href="/contacts/" target="_blank">contact us</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kotlin DSL: from Theory to Practice]]></title>
            <link>https://www.jmix.io/cuba-blog/kotlin-dsl-from-theory-to-practice</link>
            <guid>https://www.jmix.io/cuba-blog/kotlin-dsl-from-theory-to-practice</guid>
            <pubDate>Fri, 08 Dec 2017 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/623e2ff4def348858a4248ead605cb90.png">SQL, RegExp, Gradle — what do they have in common? All of them represent an example of using domain-specific languages, or DSL. Languages of this type aim to solve a specific problem, such as database querying, finding matches in the text, or build process description. Kotlin language offers a large amount of features for building your own domain-specific language. In this article we’ll discover the developer’s toolkit and implement a DSL for a real-world domain.]]></description>
            <content:encoded><![CDATA[I’ll try to explain the language syntax as simple as possible, however, the article still appeals to developers who consider Kotlin as a language for custom DSL building. At the end of the article I’ll mention Kotlin drawbacks worth taking into account. The presented code snippets are relevant for Kotlin version 1.2.0 and are available on GitHub.

## What is DSL?

All programming languages can be divided into general-purpose and domain-specific languages. SQL, regular expressions, build.gradle are often cited as examples of DSL. These languages are limited in functionalities but they are able to effectively address a certain problem. They allow to write not imperative code (we shouldn't explain how to solve the problem) but in more or less declarative way (we just declare the task) in order to obtain the solution based on the given data.

Let’s say you have the standard process definition which can be eventually changed and enhanced but generally you want to use it with different data and result formats. By creating a DSL you create a flexible tool for solving various problems within one subject domain, no matter for your DSL end user how the solution is obtained. So, you create a sort of API which, if mastered, can simplify your life and make it easier to keep the system up-to-date in the long-term.

The article deals with building an “embedded” DSL in Kotlin as a language implemented on the general-purpose languages syntax. You can read more about it <a href="https://en.wikipedia.org/wiki/Domain-specific_language#Usage_patterns" target="_blank">here</a>.

## Implementation area

To my mind, one of the best ways to use and demonstrate Kotlin DSL is testing.

Suppose that you’ve come from the Java world. How often have you been faced with declaring entity instances of an extensive data model? You’ve been likely using some builders or, even worse, special utility classes to fill the default values under the hood. How many overridden methods have you had? How often do you have to make a little changes from default values, and how much effort does this require today? If these questions stir up nothing but negative feelings, this article is for you.

That’s the way we’ve been doing for a long time in our project in the area of education: we used builders and utility classes to cover with tests one of our most important modules which is school timetable scheduling. Now this approach has given way to the Kotlin language and DSL which is used to describe test scenarios and check the results. Below you can see how we took advantage of Kotlin so that testing of the scheduling subsystem is not a torture anymore.

In this article we will dive into details of constructing a DSL which helps to test an algorithm building teachers and students schedules.

## Key tools

Here are the basic language features that allow you to write cleaner code in Kotlin and create your own DSL. The table below demonstrates the main syntax enhancements that are worth using. Take a look at it carefully. If most these tools are unfamiliar to you, you might better read the whole article. If you don’t know one or two of them, feel free to fast forward to corresponding sections. In case there’s nothing new for you, just skip to DSL drawbacks review at the end of the article. You can also welcome to propose more tools in comments.

<table style="font-size:11px;">
<tbody><tr><th width="22%">Tool</th><th width="28%">DSL syntax</th><th width="30%">General syntax</th></tr>
  <tr>
    <td><pre><code class="hljs nginx"><span class="hljs-title">Operators</span> overloading</code></pre></td>
    <td><pre><code class="hljs makefile"><span class="hljs-constant">collection</span> += element</code></pre></td>
    <td><pre><code class="hljs css"><span class="hljs-tag">collection</span><span class="hljs-class">.add</span>(<span class="hljs-tag">element</span>)</code></pre></td>
  </tr>
  <tr>
    <td><pre><code class="hljs nginx"><span class="hljs-title">Type</span> aliases</code></pre></td>
    <td><pre><code class="hljs nginx"><span class="hljs-title">typealias</span> Point = Pair<int, int=""></int,></code></pre></td>
    <td><pre><code class="hljs php">Creating empty inheritors classes <br>and other duct tapes</code></pre></td>
  </tr>
  <tr>
    <td><pre><code class="hljs cs"><span class="hljs-keyword">get</span>/<span class="hljs-keyword">set</span> methods convention</code></pre></td>
    <td><pre><code class="hljs cpp"><span class="hljs-built_in">map</span>[<span class="hljs-string">"key"</span>] = <span class="hljs-string">"value"</span></code></pre></td>
    <td><pre><code class="hljs cpp"><span class="hljs-built_in">map</span>.put(<span class="hljs-string">"key"</span>, <span class="hljs-string">"value"</span>)</code></pre></td>
  </tr>
  <tr>
    <td><pre><code class="hljs nginx"><span class="hljs-title">Destructuring</span> declaration</code></pre></td>
    <td><pre><code class="hljs nginx"><span class="hljs-title">val</span> (x, y) = Point(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)</code></pre></td>
    <td><pre><code class="hljs nginx">val p = Point(0, 0); val x = p.first; <br>val y = p.second</code></pre></td>
  </tr>
  <tr>
    <td><pre><code class="hljs coffeescript">Lambda out <span class="hljs-keyword">of</span> parentheses</code></pre></td>
    <td><pre><code class="hljs php"><span class="hljs-keyword">list</span>.<span class="hljs-keyword">forEach</span> { ... }</code></pre></td>
    <td><pre><code class="hljs php"><span class="hljs-keyword">list</span>.<span class="hljs-keyword">forEach</span>({...})</code></pre></td>
  </tr>
  <tr>
    <td><pre><code class="hljs bash">Extension <span class="hljs-built_in">functions</span></code></pre></td><td><pre><code class="hljs ruby">mylist.first(); <br><small>// there isn’t first() method<br>in mylist collection</small></code></pre></td><td><pre><code class="hljs bash">Utility <span class="hljs-built_in">functions</span></code></pre></td>
  </tr>
  <tr>
    <td><pre><code class="hljs bash">Infix <span class="hljs-built_in">functions</span></code></pre></td>
    <td><pre><code class="hljs apache"><span class="hljs-keyword">1</span> to <span class="hljs-string">"one"</span></code></pre></td>
    <td><pre><code class="hljs apache"><span class="hljs-keyword">1</span>.to(<span class="hljs-string">"one"</span>)</code></pre></td>
  </tr>
  <tr>
    <td><pre><code class="hljs coffeescript">Lambda <span class="hljs-reserved">with</span> receiver</code></pre></td>
    <td><pre><code class="hljs">Person().apply { name = «John» }</code></pre></td>
    <td><pre><code class="hljs">N/A</code></pre></td>
  </tr>
  <tr>
    <td><pre><code class="hljs nginx"><span class="hljs-title">Context</span> control</code></pre></td>
    <td><pre><code class="hljs coffeescript"><span class="hljs-property">@DslMarker</span></code></pre></td>
    <td><pre><code class="hljs">N/A</code></pre></td>
  </tr>
</tbody></table>
Found anything new? If so, let’s move on.

I omitted delegated properties intentionally, as, in my opinion, they are useless for building DSL, at least in our case. Using the features above we can write cleaner code and get rid of voluminous “noisy” syntax, making development even more pleasant (Could it be?).

I liked the comparison I met in “Kotlin in Action” book: in natural languages, as English, sentences are built of words, and grammar rules define the way of combining these words. Similarly, in DSL one operation can be constructed of several method calls, and the type check guarantees that the construction makes sense. For sure, the order of callings can not always be obvious, but it is entirely up to the DSL designer.

It is important to stress that this article examines an “embedded DSL”, so it is based on a general-purpose language, which is Kotlin.

## Final result example

Before we begin to design our own domain-specific language, I’d like to show you an example of what you’ll be able to create after reading this article. The whole code is available on GitHub repository through the <a href="https://github.com/ivan-osipov/kotlin-dsl-example" target="_blank">link</a>.  
The DSL-based code below is designed to test the allocation of a teacher for students for the defined disciplines. In this example we have a fixed timetable, and we check if classes are placed in both teacher’s and students’ schedules.

    schedule {
        data {
            startFrom("08:00")
            subjects("Russian",
                    "Literature",
                    "Algebra",
                    "Geometry")
            student {
                name = "Ivanov"
                subjectIndexes(0, 2)
            }
            student {
                name = "Petrov"
                subjectIndexes(1, 3)
            }
            teacher {
               subjectIndexes(0, 1)
               availability {
                 monday("08:00")
                 wednesday("09:00", "16:00")
               } 
            }
            teacher {
                subjectIndexes(2, 3)
                availability {
                    thursday("08:00") + sameDay("11:00") + sameDay("14:00")
                }
            }
            // data { } won't be compiled here because there is scope control with
            // @DataContextMarker
        } assertions {
            for ((day, lesson, student, teacher) in scheduledEvents) {
                val teacherSchedule: Schedule = teacher.schedule
                teacherSchedule[day, lesson] shouldNotEqual null
                teacherSchedule[day, lesson]!!.student shouldEqual student
                val studentSchedule = student.schedule
                studentSchedule[day, lesson] shouldNotEqual null
                studentSchedule[day, lesson]!!.teacher shouldEqual teacher
            }
        }
    }

## Toolkit

All the features for building a DSL have been listed above. Each of them is used in the example from the previous section. You can examine how define such DSL constructs in my <a href="https://github.com/ivan-osipov/kotlin-dsl-example" target="_blank">project</a> on GitHub.  
We will refer to this example again below in order to demonstrate the usage of different tools. Please bear in mind that the described approaches are for illustrative purposes only, and there may be other options to achieve the desired result.  
So, let’s discover these tools one by one. Some language features are most powerful when combined with the others, and the first in this list is the lambda out of parentheses.

### Lambda out of parentheses

<a href="https://kotlinlang.org/docs/reference/lambdas.html#higher-order-functions" target="_blank">Documentation</a>  

Lambda expression is a code block that can be passed into a function, saved or called. In Kotlin the lambda type is defined in the following way: (list of param types) -> returned type. Following this rule, the most primitive lambda type is () -> Unit, where Unit is an equivalent of Void with one important exception. At the end of the lambda we don’t have to write the _return…_ construction. Thereby, we always have a returned type but in Kotlin this is done implicitly.

Below is a basic example of assigning lambda to a variable:

    val helloPrint: (String) -> Unit = { println(it) }

Usually the compiler tries to infer the type from the already known ones. In our case there is a parameter. This lambda can be invoked as follows:

    helloPrint("Hello")

In the example above the lambda takes one parameter. Inside the lambda this parameter is called it by default, but if there were more, you would have to specify their names explicitly or use the underscore to ignore them. See such case below:

    val helloPrint: (String, Int) -> Unit = { _, _ -> println("Do nothing") }
    helloPrint("Does not matter", 42) //output: Do nothing

The base tool - which you may already know from Groovy - is the lambda out of parentheses. Look again at the example from the very beginning of the article: almost every use of curly brackets, except the standard constructions, is a lambda. There are at least two ways of making an x { … }:-like construction:

*   the object x and its unary operator _invoke_ (we’ll discuss it later);
*   the function x that takes a lambda.

In both cases we use lambda. Let’s suppose there is a function x(). In Kotlin, if a lambda is the last argument of a function, it can be placed out of parentheses, furthermore, if a lambda is the only function’s parameter, the parentheses can be omitted. As a result, the construction x({…}) can be transformed into x() {}, and then, by omitting the parentheses, we get x {}. This is how we declare such functions:

    fun x( lambda: () -> Unit ) { lambda() }

In concise form a single-line function can be also written like this:

    fun x( lambda: () -> Unit ) = lambda()

But what if x is a class instance, or an object, instead of a function? Below is another interesting solution based on a fundamental domain-specific concept: operators overloading.  

### Operator overloading

<a href="https://kotlinlang.org/docs/reference/operator-overloading.html" target="_blank">Documentation</a>  

Kotlin provides wide but limited variety of operators. The _operator_ modifier enables to define functions by conventions that will be called under certain conditions. As an obvious example, the plus function is executed if you use the “+” operator between two objects. The complete list of operators can be found in the docs by the link above.  
Let’s consider a less trivial operator _invoke_. This article’s main example starts with the _schedule { }_ construct that defines the code block, responsible for testing the schedule. This construct is built in a slightly different way to the one mentioned above: we use the invoke operator + “lambda out of parentheses”. Having defined the invoke operator, we can now use the _schedule(...)_ construct, although _schedule_ is an object. In fact, when you call _schedule(...)_, the compiler interprets it as _schedule.invoke(…)_. Let’s see how _schedule_ is declared:

    object schedule {
        operator fun invoke(init: SchedulingContext.() -> Unit)  { 
            SchedulingContext().init()
        }
    }

The _schedule_ identifier refers us to the only _schedule_ class instance (singleton) that is marked by the special keyword _object_ (you can find more information about such objects <a href="https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations" target="_blank">here</a>). Thus, we call the _invoke_ method of the _schedule_ instance, receiving lambda as a single parameter and placing it outside of the parentheses. As a result, the _schedule {… }_ construction matches the following:

    schedule.invoke( { code inside lambda } )

However, if you look at the invoke method carefully, you’ll see not a common lambda but a “lambda with a handler” or “lambda with context” which type is defined as

    SchedulingContext.() -> Unit

Let’s examine it in details.

### Lambda with a handler

<a href="https://kotlinlang.org/docs/reference/lambdas.html#function-literals-with-receiver" target="_blank">Documentation</a>  

Kotlin enables us to set a context for lambda expressions (context and handler mean same here). Context is just an object. The context type is defined together with the lambda expression type. Such lambda acquires properties of a non-static method in the context class but only has access to the public methods of this class.  
While the type of a normal lambda is defined like () -> Unit, the type of a lambda with X context is defined as follows: X.()-> Unit, and, if normal lambdas can be called in a usual way:

    val x : () -> Unit = {}
    x()

lambda with context requires a context:

    class MyContext

    val x : MyContext.() -> Unit = {}

    //x() //won’t be compiled, because a context isn’t defined 

    val c = MyContext() //create the context

    c.x() //works

    x(c) //works as well

I’d like to remind that we have defined the invoke operator in the schedule object (see the preceding paragraph) that allows us to use the construct:

    schedule { }

The lambda we are using has the context of SchedulingContext type. This class has a data method in it. As a result, we get the following construct:

    schedule {
        data {
            //...
        }
    }

As you have probably guessed, the data method also takes a lambda with context, however it is a different context. Thus, we get nested structures having several contexts inside simultaneously. To get the idea of how it works, let’s remove all syntactic sugar from the example:

    schedule.invoke({
        this.data({
        })
    })

As you can see, it’s all fairly simple. Let’s take a look at the invoke operator implementation.

    operator fun invoke(init: SchedulingContext.() -> Unit)  { 
        SchedulingContext().init()
    }

We call the constructor for the context SchedulingContext(), and then with the created object (_context_) we call the lambda with the _init_ identifier that we have passed as a parameter. This resembles a lot a general function call. As a result, in one single line SchedulingContext().init() we create the context and call the lambda passed to the operator. For more examples, consider _apply_ and _with_ methods from Kotlin standard library.

In the last examples we discovered the _invoke_ operator and its combination with other tools. Next, we will focus on the tool that is formally an operator and makes the code cleaner - the _get/set methods convention_.

### get/set methods convention

<a href="https://kotlinlang.org/docs/reference/operator-overloading.html#indexed" target="_blank">Documentation</a>  

When creating a DSL we can implement a way to access maps by one or more keys. Let’s look at the example below:

    availabilityTable[DayOfWeek.MONDAY, 0] = true
    println(availabilityTable[DayOfWeek.MONDAY, 0]) //output: true

In order to use square brackets, we need to implement _get_ or _set_ methods (depending on what we need, read or update) with an _operator_ modifier. You can find an example of such implementation in the _Matrix_ class on <a href="https://github.com/ivan-osipov/kotlin-dsl-example" target="_blank">GitHub</a>. It is a simple wrapper for matrix operations. Below you see a code snippet on the subject:

    class Matrix(...) {
        private val content: List>
        operator fun get(i: Int, j: Int) = content[i][j]
        operator fun set(i: Int, j: Int, value: T) { content[i][j] = value }
    }

You can use any _get_ and _set_ parameter types, the only limit is your imagination. You are free to use one or more parameters for get/set functions to provide a convenient syntax for data access. Operators in Kotlin provide lots of interesting features that are described in the <a href="https://kotlinlang.org/docs/reference/operator-overloading.html" target="_blank">documentation</a>.

Surprisingly, there is a _Pair_ class in the Kotlin standard library. Larger part of developers community finds _Pair_ harmful: when you use _Pair_, the logic of linking two objects is lost, thus it is not transparent why they are paired. The two tools I’ll show you next will demonstrate how to keep the pair sensemaking without creating additional classes.

### Type aliases

<a href="https://kotlinlang.org/docs/reference/type-aliases.html" target="_blank">Documentation</a>  

Suppose we need a wrapper class for a geo point with integer coordinates. Actually, we could use the Pair <int, int="">class, but having such variable we can in a moment lose the understanding of why we have paired these values.  
A straightforward solution is either to create a custom class or something even worse. Kotlin enriches the developer’s toolkit by type aliases with the following notation:

    typealias Point = Pair

In fact, it is nothing but renaming a construct. Due to this approach we don’t need to create the _Point_ class anymore, as it would only duplicate the _Pair_. Now we can create a point in this way:

    val point = Point(0, 0)

However, the _Pair_ class has two attributes, _first_ and _second_, that we need to rename somehow to blur any differences between the needed _Point_ and the initial _Pair_ class. For sure, we are not able to rename the attributes themselves (however you can create <a href="https://kotlinlang.org/docs/reference/extensions.html#extension-properties" target="_blank">extension properties</a>), but there is one more notable feature in our toolkit called _destructuring declaration_.  

### Destructuring declaration

<a href="https://kotlinlang.org/docs/reference/multi-declarations.html#destructuring-declarations" target="_blank">Documentation</a>  

Let’s consider a simple case: suppose we have an object of the _Point_ type which is, as we already know, just a renamed type Pair<int, int="">. If we look at the _Pair_ class implementation in the standard library, we’ll see that it has a data modifier which directs the compiler to implement _componentN_ methods within this class. Let’s learn more about it.</int,>

For any class, we can define the _componentN_ operator that will be in charge of providing access to one of the object attributes. That means that calling _point.component1_ will be equal to calling _point.first_. Why do we need such a duplication?

Destructuring declaration is a means of “decomposing” an object to variables. This functionality allows us to write constructions of the following kind:

    val (x, y) = Point(0, 0)

We can declare several variables at once, but what values will they be assigned? That’s why we need the generated _componentN_ methods: using the index starting from 1 instead of N, we can decompose an object to a set of its attributes. So, the above construct equals to the following:

    val pair = Point(0, 0)
    val x = pair.component1()
    val y = pair.component2()

which, in turn, is equal to:

    val pair = Point(0, 0)
    val x = pair.first
    val y = pair.second

where _first_ and _second_ are the Point object attributes.The _for_ loop in Kotlin looks as follows, where x takes the values 1, 2, and 3:

    for(x in listOf(1, 2, 3)) { … }

Pay attention to the assertions block in the DSL from the main example. I’ll repeat a part of it for convenience:

    for ((day, lesson, student, teacher) in scheduledEvents) { … }

This line should be evident. We iterate through a collection of _scheduledEvents_, each elements of which is decomposed into 4 attributes.  

### Extension functions

<a href="https://kotlinlang.org/docs/reference/extensions.html#extensions" target="_blank">Documentation</a>  

Adding new methods to objects from third-party libraries or to the Java Collection Framework is what a lot of developers have been dreaming about. Now we have such opportunity. This is how we declare extension functions:

    fun AvailabilityTable.monday(from: String, to: String? = null)

Compared to the standard method, we add the class name as a prefix to define the class we extend. In the example above AvailabilityTable is an alias for the Matrix type and, as aliases in Kotlin are nothing but renaming, this declaration is equal to the one below, which is not always convenient:

    fun Matrix.monday(from: String, to: String? = null)

Unfortunately, there's nothing we can do here, except not using the tool, or adding methods only to a specific context class. In this case, the magic only appears where you need it. Moreover, you can use such functions even for extending interfaces. As a good example, the _first_ method extends any _iterable object_:

    fun  Iterable.first(): T

In essence, any collection based on the _Iterable_ interface, despite of the element type, gets the _first_ method. It is worth mentioning that we can place an extension method in the context class and thereby have access to the extension method only in this very context (similarly to lambda with a context). Furthermore, we can create extension functions for _Nullable_ types (the explanation of _Nullable_ types is out of scope here, for more details see <a href="https://kotlinlang.org/docs/reference/null-safety.html#nullable-types-and-non-null-types" target="_blank">this link</a>). For example, that’s how we can use the function _isNullOrEmpty_ from the standard Kotlin library that extends the _CharSequence_ type:

    val s: String? = null
    s.isNullOrEmpty() //true

Below is this function’s signature:

    fun CharSequence?.isNullOrEmpty(): Boolean

When working with such Kotlin extension functions from Java, they are accessible as static functions.  

### Infix functions

<a href="https://kotlinlang.org/docs/reference/functions.html#infix-notation" target="_blank">Documentation</a>

One more way to sugar-coat our syntax is to use infix functions. Simply said, this tool helps us to get rid of excessive code in simple cases. The assertions block from the main snippet demonstrates this tool’s use case:

    teacherSchedule[day, lesson] shouldNotEqual null

This construction is equivalent to the following:

    teacherSchedule[day, lesson].shouldNotEqual(null)

In some cases brackets and dots can be redundant. For such cases we can use the _infix_ modifier for functions.  
In the code above, the construct teacherSchedule[day, lesson] returns a schedule element, and the function shouldNotEqual checks this element is not null.  
To declare an infix function, you need to:

*   use the infix modifier;
*   use only one parameter.

Combining the last two tools we can get the code below:

    infix fun  T.shouldNotEqual(expected: T)

Note that the generic type by default is an Any inheritor (not Nullable), however, in such cases we cannot use null, that’s why you should explicitly define the type Any?  

### Context control

<a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-dsl-marker/index.html" target="_blank">Documentation</a>  

When we use a lot of nested contexts, on the lower level we risk getting a wild mix. Due to lack of control the following meaningless construct becomes possible:

    schedule { //context SchedulingContext
        data { //context DataContext + external context SchedulingContext
            data { } //possible, as there is no context control
        }
    }

Before Kotlin v.1.1 there had already been a way to avoid the mess. It lies in creating a custom method data in a nested context DataContext, and then marking it with the Deprecated annotation with the ERROR level.

    class DataContext {
        @Deprecated(level = DeprecationLevel.ERROR, message = "Incorrect context")
        fun data(init: DataContext.() -> Unit) {}
    }

This approach eliminates the possibility of building incorrect DSL. Nevertheless, the big number of methods in SchedulingContext would have made us doing a lot of routine work discouraging from any context control.  
Kotlin 1.1 offers a new control tool — the @DslMarker annotation. It is applied to your own annotations which, in turn, are used for marking your contexts. Let’s create an annotation and mark it with the new tool from our toolkit:

    @DslMarker
    annotation class MyCustomDslMarker

Now we need to mark up the contexts. In the main example these are SchedulingContext and DataContext. As far as we annotate both classes with the common DSL marker, the following happens:

    @MyCustomDslMarker
    class SchedulingContext { ... }

    @MyCustomDslMarker
    class DataContext { ... }

    fun demo() {
        schedule { //context SchedulingContext
            data { //context DataContext + external context SchedulingContext is forbidden
                // data { } //will not compile, as contexts are annotated with the same DSL marker
            }
        }
    }

With all the benefits of this cool approach saving so much time and effort, one problem still remains. Take a look at the main example, or, more precisely, to this part of the code:

    schedule {
        data {
            student {
                name = "Petrov"
            }
            ...
        }
    }

In this case on the third nesting level we get the new context Student which is, in fact, an entity class, so we are expected to annotate part of the data model with @MyCustomDslMarker, which is incorrect, to my opinion. In the Student context the data {} calls are still forbidden, as the external DataContext is still in its place, but the following constructions remain valid:

    schedule {
        data {
            student {
                student { }
            }
        }
    }

Attempts to solve the problems with annotations will lead to mixing business logic and testing code, and that is certainly not the best idea. Three solutions are possible here:

1.  Using an extra context for creating a student, for example, StudentContext. This smells like madness and outweighs the benefits of @DslMarker.
2.  Creating interfaces for all entities, for example, IStudent (no matter the name), than creating stub-contexts that implement these interfaces, and finally delegating the implementation to the student objects, and that verges on madness, too.

    @MyCustomDslMarker
    class StudentContext(val owner: Student = Student()): IStudent by owner

4.  Using the @Deprecated annotation, as in the examples above. In this case it looks like the best solution to use: we just add a deprecated extension method for all Identifiable objects.

        @Deprecated("Incorrect context", level = DeprecationLevel.ERROR)
        fun Identifiable.student(init: () -> Unit) {}

To sum it up, combining various tools empowers you to build a very convenient DSL for your real-world purposes.  

## Cons of DSL use

Let’s try to be more objective concerning the use of DSL in Kotlin and find out the drawbacks of using DSL in your project.

### Reuse of DSL parts

Imagine you have to reuse a part of your DSL. You want to take a piece of your code and enable to replicate it easily. Of course, in simplest cases with a single context we can hide the repeatable part of DSL in an extension function, but this will not work in most cases.

Perhaps you could point me towards better options in comments, because for now only two solutions come to my mind: adding “named callbacks” as a part of DSL or spawning lambdas. The second one is easier but can result in a living hell when you try to understand the calls sequence. The problem is the more imperative behaviour we have, the less benefits remain from DSL approach.

### This, it!?

Nothing’s easier than losing the meaning of the current “this” and “it” while working with your DSL. If you use “it” as a default parameter name where it can be replaced by a meaningful name, you’d better do so. It’s better to have a bit of obvious code than non-obvious bugs in it.

The notion of context can confuse one who had never faced it. Now, as you have “lambdas with a handler” in your toolkit, unexpected methods inside DSL are less likely to appear. Just remember, in worst case you can set the context to a variable, for example, val mainContext = this

### Nesting

This issue relates closely to the first drawback in this list. The use of nested in nested in nested constructions shifts all your meaningful code to the right. Up to a certain limit this shift may be acceptable, but when it’s shifted too much, it would be reasonable to use lambdas. Of course, this will not decrease your DSL’s readability but can be a compromise in case your DSL implies not only compact structures but also some logic. When you create tests with a DSL (the case covered by this article), this issue is not acute as the data is described with compact structures.

### Where are the docs, Lebowski?

When you first try to cope with somebody’s DSL, you will almost certainly wonder where is the documentation. On this point I believe that if your DSL is to be used by others, usage examples will be the best docs. Documentation itself is important as an additional reference, but it is not very friendly to a reader. A domain-specific practitioner will normally start with the question “What do I call to get the result?”, so in my experience, the examples of similar cases will better speak for themselves.

## Conclusion

We’ve got an overview of the tools that enable you to design your own custom domain-specific language with ease. I hope you now see how it works. Feel free to suggest more tools in comments.  
It is important to remember that DSL is not a panacea. Of course, when you get such a powerful hammer, everything looks like a nail, but it isn’t. Start small, create a DSL for tests, learn from your mistakes, and then, experienced, consider other usage areas.</int,>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Scheduled Tasks at Design Time]]></title>
            <link>https://www.jmix.io/cuba-blog/scheduled-tasks-at-design-time</link>
            <guid>https://www.jmix.io/cuba-blog/scheduled-tasks-at-design-time</guid>
            <pubDate>Wed, 11 Oct 2017 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/24ccf2156ea7471286af49e4273a8ea6.png">The article introduces a CUBA application component that allows developers to move the definition of Scheduled Tasks to design time using annotations. It explains when and why this approach brings advantages over the standard way of defining scheduled tasks at runtime. Also, this article touches some technical aspects of how this application component is implemented.]]></description>
            <content:encoded><![CDATA[If you have developed at least one project on CUBA Platform or even spent a few hours discovering it you have probably noticed a strong intention to move a lot of things to runtime: role and row level security (CRUD permissions over entities and their attributes, screens and their elements, access to the row-level data), dynamic attributes (implementation for the EAV approach), entity log (for auditing all changes over entities), JMX console (for remote application maintenance), scheduled tasks (for managing repetitive tasks, such as cache updates or e-mail queue processing) and so on. Simply saying, everything that could be managed from runtime is designed in this way.

Such runtime centric approach gives great flexibility for maintaining an application on the fly. For example, if there is a need to disable some CRUD actions for a certain user or add a few properties to an entity, it will not require a long chain of development, testing and redeployment procedures.

Looks great, however, sometimes an application requires to have some of these runtime-defined features by design. Let's take a real-world example from my practice: we have thousands of sensors (installed in fields to measure some metrics of remote equipment) sending tons of raw data every second. Before it goes available for other services (other CUBA applications, that consume this information) this data must be preprocessed (using statistical algorithms to clean up the dataset from measurement noise). This raw data is being processed once an hour by a scheduled task. In this certain case, if we forget to set up the preprocessing scheduled task at runtime, the solution simply will not do its main job - supply data to other microservices. So, the scheduled task should be there by design and not set up occasionally, on demand.

## SQL Scripts

The first and the most straightforward solution we had taken is putting all required scheduled tasks into the initialization SQL scripts, which will be executed on server startup. So, we set up everything we need in a staging server, use the standard functionality of the CUBA Platform to generate insert statements (see the animation below) and copy-paste them to the initialization and update scripts. The rest will be handled by the platform itself as it is described in <a href="https://doc.cuba-platform.com/manual-6.6/db_update_server.html" target="_blank">this chapter</a> of the documentation.

![text]({{strapiUrl}}/uploads/cae08613d4d34f46b58d6e5fc40dc553.gif)

This solution worked absolutely fine, except for a few things.

SQL scripts are not any good in terms of further support. For instance, if we refactor the names of our classes or methods or even method parameters, we will need to adjust manually all scripts of the following type:

<pre style="overflow-x: scroll;">insert into SYS_SCHEDULED_TASK 
(ID, CREATE_TS, CREATED_BY, UPDATE_TS, UPDATED_BY, DELETE_TS, DELETED_BY, DEFINED_BY, BEAN_NAME, METHOD_NAME, CLASS_NAME, SCRIPT_NAME, USER_NAME, IS_SINGLETON, IS_ACTIVE, PERIOD, TIMEOUT, START_DATE, CRON, SCHEDULING_TYPE, TIME_FRAME, START_DELAY, PERMITTED_SERVERS, LOG_START, LOG_FINISH, LAST_START_TIME, LAST_START_SERVER, METHOD_PARAMS, DESCRIPTION) 
values ('880db2c6-f2dc-ab8d-3b5a-ebe5544c25d2', '2017-10-10 12:41:59', 'test_admin', '2017-10-10 12:41:59', null, null, null, 'B', 'scheduler_TestScheduler', 'testCorrectScheduledTasks', null, null, 'admin', true, true, 5, 5, '2000-01-01 00:00:00', null, 'P', 10, null, 'localhost:8080/scheduler-core', true, true, null, null, '<?xml version="1.0" encoding="UTF-8"?>

<params>
  <param type="java.lang.String" name="a">a-value</param>
  <param type="java.lang.String" name="b">b-value</param>
  <param type="java.lang.String" name="code">test-periodical-scheduler</param>
</params>
', 'Test periodical scheduler');

</pre>

Imagine if you have 10, 15 or a hundred of such statements...

Another problem we had is that looking at the sources, developers do not understand the importance of methods which are specified in a scheduled task for repetitive execution. We even had situation when a few such methods have been removed by a developer, because the IDE marked them as unused :). I have to notice that the IDE was absolutely right, as well as the developer, who simply wanted to clean up the source code from unused artifacts. This particular situation made me rethink the way of SQL statements.

## Annotations

We had to come up with a transparent way to define scheduled tasks, so that we can refactor the source code without the risk to break them down. In response to these requirements we decided to take the very well known approach of annotations, which has originally been designed in Java exactly for this purpose, to move configurations from separate files (for example XML configurations) into inline declarations, making the source code very readable and transparent for developers.

Let me share the result of how we define scheduled tasks at design time now:
```
    @Component
    public class TestScheduler implements TestSchedulerInterface {

        @Inject
        private Logger log;

        @Override
        @ScheduledBeanMethod(
                code = "test_scheduler",
                isSingleton = true,
                isActive = true,
                period = @Period(period = 5, 
                        startDate = "01/01/2000 00:00:00"),
                logStart = true,
                methodParams = {
                        @MethodParam(name = "a", value = "a-value"),
                        @MethodParam(name = "b", value = "b-value")
                }
        )
        public void testPeriodMethod(String a, String b) {
            log.debug("test method executed with parameters: {}, {}", a, b);
        }
    }
```
Now, to define a scheduled task, a developer simply marks a method of a bean with the @ScheduledBeanMethod annotation. This annotation will be read at the server startup by an annotation loader which will create the corresponding scheduled task in CUBA. The result will not be any different from if you would create it manually in the standard CUBA way, but now you can be sure that nobody will forget to create it and nobody will remove this part of code as unused.

### How it Works Under the Hood

First, we need to find all the annotated methods, which is done by the <a href="https://github.com/aleksey-stukalov/cuba-scheduler-annotation/blob/master/modules/core/src/com/acc/cuba/tools/scheduler/core/ScheduledTaskLoader.java" target="_blank"><i>ScheduledTaskLoader</i></a> bean. It implements the standard _BeanPostProcessor_ Spring interface, which gives you a hook to post process Spring beans right after their initialization. So, using the following code we gather all beans with the @ScheduledBeanMethod annotated methods into one collection:

```
<div style="overflow-x: scroll;">
	@Component
	public class ScheduledTaskLoader implements BeanPostProcessor {
	   ...
	   private List<ScheduledMethodContext> scheduleAnnotatedMethods = new ArrayList<>();
	   ...
	   @Overrid
	   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		  return bean;
	   }

	   /**
	   * The method scans all beans, that contain methods, annotated as {@link ScheduledBeanMethod}
	   */
	   @Override
	   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		  Class<?> targetClass = AopUtils.getTargetClass(bean);

                  Map<Method, Set<ScheduledBeanMethod>> annotatedMethods = MethodIntrospector.selectMethods(targetClass,
				  (MethodIntrospector.MetadataLookup<Set<ScheduledBeanMethod>>) method -> {
					  Set<ScheduledBeanMethod> scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(
							  method, ScheduledBeanMethod.class, ScheduledBeanMethods.class);
					  return (!scheduledMethods.isEmpty() ? scheduledMethods : null);
				  });

		  for (Map.Entry<Method, Set<ScheduledBeanMethod>> entry : annotatedMethods.entrySet()) {
		   scheduleAnnotatedMethods.add(new ScheduledMethodContext(beanName, entry.getKey(), entry.getValue()));
		  }

		  return bean;
	   }
	}
</div>
```
<br>

Another thing here I would like to pay attention to is that the _@ScheduledBeanMethod_ annotation is designed to be repeatable (as long as you might want to schedule the same method a number of times with different input parameters or other scheduling settings; see an example in the integration tests <a href="https://github.com/aleksey-stukalov/cuba-scheduler-annotation/blob/master/modules/core/test/com/acc/cuba/tools/scheduler/TestScheduler.java" target="_blank">here</a>), so we use the _AnnotatedElementUtils#getMergedRepeatableAnnotations_ method to get all of them.

So, after _Spring_ initialized all its beans our _ScheduledTaskLoader_ already knows which methods should be wrapped into Scheduled Tasks. The only thing left is to create the corresponding instances of the system _ScheduledTask_ entity right after application startup. This can be implemented in the same way as it is shown in <a href="https://doc.cuba-platform.com/manual-6.6/app_start_recipe.html" target="_blank">this recipe</a> from the CUBA Platform cookbook:

```
    @Component("scheduler_AppLifecycle")
    public class AppLifecycle implements AppContext.Listener {

       @Inject
       private ScheduledTaskLoader taskLoader;

       @Inject
       private Authentication auth;

       @Override
       public void applicationStarted() {
           auth.withUser(null, () -> {
               taskLoader.loadScheduledMethods();
               return null;
           });
       }

       …

       @PostConstruct
       public void postConstruct() {
          AppContext.addListener(this);
       }

    }
```

So, as you see it's not rocket science, but very effective. The same hook at startup can be used for solving variety of tasks at the startup stage, for example, sample data generation for testing and debugging or self-registering a service instance in a service registry to be become discoverable for others if you use the microservice architecture.

## Summary

In conclusion, I would like to share <a href="https://github.com/aleksey-stukalov/cuba-scheduler-annotation">my solution</a> with the members of the CUBA community who have faced with the same or similar experience as I highlighted in this article. This is an application component, which means that you can easily attach it to any of your CUBA projects following <a href="https://doc.cuba-platform.com/manual-6.6/app_components_sample.html" target="_blank">this guide</a>.

Finally, If you have something to contribute or even publish your own application component making our ecosystem better you are very welcome to contact us via the <a href="https://www.cuba-platform.com/discuss/" target="_blank">support forum</a> or drop a message from <a href="https://www.cuba-platform.com/contacts" target="_blank">here</a>. In case you already created some open source app components, we recommend to mark them with the _cuba-component_ tag, so they become available through <a href="https://github.com/search?q=topic%3Acuba-component&type=Repositories" target="_blank">this link</a> on GitHub.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's New in CUBA Platform 6.6]]></title>
            <link>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-6-6</link>
            <guid>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-6-6</guid>
            <pubDate>Thu, 24 Aug 2017 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/6da5ff27c14a471d9de2f72303c5c445.png">A few weeks ago we published the new minor release of CUBA platform and Studio. As always, it brings some very awaited features and improvements, making development process more straightforward, transparent and fast.]]></description>
            <content:encoded><![CDATA[This article covers major enhancements of Platform and Studio. The full list of changes is available in the corresponding release notes:

<a href="http://files.cuba-platform.com/cuba/release-notes/6.6/#platform" target="_blank">platform-6.6-release</a>  
<a href="http://files.cuba-platform.com/cuba/release-notes/6.6/#studio" target="_blank">studio-6.6-release</a>

## Contents

[Uber JAR](#single-uber-jar)  
[Polymer UI in Single WAR](#polymer-ui-in-single-war)  
[Health Check URL](#health-check-url)  
[Image Component](#image-component)  
[REST API Custom Authentication](#rest-api-custom-authentication)  
[User Session Log](#user-session-log)  
[Cancelable Report Generation](#cancelable-report-generation)  
[REST API Services and Queries](#rest-api-services-and-queries)  
[Mapping Database Views for Migration from Legacy DB](#mapping-database-views-for-migration-from-legacy-db)  
[Test Infrastructure Stubs](#test-infrastructure-stubs)  
[Summary](#summary)

## <a id="single-uber-jar"></a>Single Uber Jar

In the previous version we announced the Uber JAR feature, allowing developers to build executable jars for CUBA applications in a few clicks from CUBA Studio. However, the final build consisted of two parts: app-core.jar and app.jar, referring to server and client parts of the application.

Now, the buildUberJar Gradle task can now be configured to build a single all-in-one JAR file including all application blocks.

All you have to do is to set to true the singleJar parameter (it is false by default to preserve existing configurations), for example:

<pre>task buildUberJar(type: CubaUberJarBuilding) {
    singleJar = true
    coreJettyEnvPath = 'modules/core/web/META-INF/jetty-env.xml'
    appProperties = ['cuba.automaticDatabaseUpdate' : true]
}
</pre>

After building, you can run your application by calling a single command:  
java -jar app.jar

## <a id="polymer-ui-in-single-war"></a>Polymer UI in Single WAR

In the past half year we have noticed quite intensive growth of the community, who use Google Polymer client as a customer-faced UI for CUBA applications.  
So, keeping track of simplifying the deployment process we supported the Polymer client in single WAR. Now, if you use the single WAR deployment option, the Polymer UI will be available via <app-name>/front URL, for example:</app-name>

<a href="http://localhost:8080/app/front" target="_blank">http://localhost:8080/app/front</a>

## <a id="health-check-url"></a>Health Check URL

Following the trend of microservices, now every application block deployed as a web application provides a health check URL, for example <a href="http://localhost:8080/app/rest/health" target="_blank">http://localhost:8080/app/rest/health</a>. An HTTP GET request of this URL returns ok if the block is alive.

## <a id="image-component"></a>Image Component

In the previous versions there was no specialized data aware UI component to show images. So, developers had to use the <a href="https://demo.cuba-platform.com/sampler/#!" target="_blank">Embedded</a> component to illustrate pictures in the UI.

Now, the new <a href="https://doc.cuba-platform.com/manual-6.6/gui_Image.html" target="_blank">Image</a> component greatly simplifies displaying of images from different sources:

*   from an entity attribute of FileDescriptor or byte array types
*   from a classpath resource
*   from a file
*   from an input stream
*   from a theme resource
*   from a URL

The component can also be bound to a datasource and configured declaratively.

## <a id="rest-api-custom-authentication"></a>REST API Custom Authentication

In response to requests from our community we reworked authentication process to provide an easier way to implement additional authentication mechanisms for REST API, e.g. login-by-link, social login (Facebook, Twitter, etc.) or LDAP. It can be done using the new REST API component: OAuthTokenIssuer.

The process is as follows:

*   Implement custom Spring MVC controller that performs custom authentication.
*   Register this controller in REST API Spring context using a custom Spring XML file and cuba.restSpringContextConfig application property.
*   If a user is authenticated, the controller creates OAuth2 Access token using the OAuthTokenIssuer bean.
*   Created OAuth2 token is returned to the user.
*   After that, the REST API client can use the OAuth2 token as usual passing it to REST API.

We also published a <a href="https://github.com/cuba-platform/sample-social-login" target="_blank">sample</a> project, that shows how you can use this feature in your applications.

## <a id="user-session-log"></a>User Session Log

Tracking users activity is quite common feature in the world of enterprise applications. Now, this requirement is covered right out of the box. Simply find the User Session Log item under the Administration menu and enable logging in your system. The system will show you who, where and when accessed the system.

![text]({{strapiUrl}}/uploads/0d856c5f29174ac6b7355848de600a8f.png)

## <a id="cancelable-report-generation"></a>Cancelable Report Generation

Sometimes report generation is not a fast process. Now, to enable cancellation while report generation you should only set the reporting.useBackgroundReportProcessing application property to ture and all reports executing in a background thread can be aborted if a user clicks Cancel button or by a timeout. When a report is cancelled or timed out, the execution is aborted both on the middleware and in the database.

## <a id="rest-api-services-and-queries"></a>REST API Services and Queries

The new version of Studio provides the user interface for configuring queries and service methods for REST API. So, now, managing your REST API becomes as simple as it is shown in the pictures below:

![text]({{strapiUrl}}/uploads/2ba364ac08dc4bb394ce5b7bd3c54cc6.png)

![text]({{strapiUrl}}/uploads/74350fbb100c4e40a37457a08b416d21.png)

## <a id="mapping-database-views-for-migration-from-legacy-db"></a>Mapping Database Views for Migration from Legacy DB

Now database views can be mapped to entities when generating model from an existing database. The only restriction is that the view must contain a column or a set of columns suitable for the entity identifier.  
Views are shown together with tables in the same list. If you select a view for mapping, on the next screen its status will be **Choose primary key for DB view**. Click the **Choose PK** button at the bottom and select columns for the primary key:

![text]({{strapiUrl}}/uploads/113d8813590b4257b8b627d037d4604a.png)

## <a id="test-infrastructure-stubs"></a>Test Infrastructure Stubs

If you create a new project based on the platform 6.6+, Studio will generate the <a href="https://doc.cuba-platform.com/manual-6.6/integration_tests_mw.html" target="_blank">integration test</a> infrastructure in its core module. You can find the created classes in the modules/core/test folder. You can run the tests from the IDE or from the command line (provided that you have created the Gradle wrapper) by calling

<pre>gradlew test
</pre>

## <a id="summary"></a>Summary

Traditionally, let me thank all proactive members of our community, who participated the platform development and helped with testing the release candidate version. As long as the platform now <a href="https://www.cuba-platform.com/blog/pull-requests-wanted" target="_blank">fully open for your contribution</a> we will be happy to see not only your <a href="https://www.cuba-platform.com/discuss/c/ideas" target="_blank">ideas on our forum</a>, but also pull requests with their implementation! You are welcome to watch the <a href="https://vimeo.com/228186583" target="_blank">recorded video</a> of the live webinar session about the release.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Pull Requests Wanted!]]></title>
            <link>https://www.jmix.io/cuba-blog/pull-requests-wanted</link>
            <guid>https://www.jmix.io/cuba-blog/pull-requests-wanted</guid>
            <pubDate>Mon, 24 Jul 2017 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/7ebefd521d5b46ecb5eae62f4ef7fd9b.png">Since CUBA Platform was published as an open-source solution we are constantly moving towards increasing transparency. About a year ago we made CUBA issue tracker accessible, followed by publishing the platform roadmap. Finally, now we encourage everyone to contribute the code and influence CUBA Platform development.]]></description>
            <content:encoded><![CDATA[Since CUBA Platform was published as an open-source solution we are constantly moving towards increasing transparency. The source code is available on [GitHub](https://github.com/cuba-platform/cuba/). About a year ago we made CUBA issue tracker accessible, followed by publishing the platform roadmap. Finally, now we encourage everyone to contribute the code and influence CUBA Platform development.

## How it relates to you

Contributing code and bug reporting has become easier - both can be done without leaving GitHub. All changes will be reviewed by our team as pull requests.

## The process

In case you are going to contribute a patch to CUBA Platform just follow these steps:

1.  Create a pull request.
2.  Accept the Contributor License Agreement.
3.  Make sure you respond to our comments, if any.
4.  Wait for merge and release. We will proceed to your request as soon as possible.

The detailed description is posted in our [Contributor Guide](https://github.com/cuba-platform/cuba/blob/master/CONTRIBUTING.md). We are looking forward to your pull requests and of course bug reports!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's New in CUBA Platform 6.5]]></title>
            <link>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-6-5</link>
            <guid>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-6-5</guid>
            <pubDate>Wed, 24 May 2017 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/0cf9f4c608864f808a5481c46f6e1611.png">As you already might have noticed we have published the new minor release of CUBA platform and Studio. The new version introduces mostly enhancements of the existing functionality, however, there are a few useful features have been included in 6.5.

This article covers major enhancements of Platform and Studio. The full list of changes is available in the corresponding release notes:

<a href="http://files.cuba-platform.com/cuba/release-notes/6.5/#platform" target="_blank">platform-6.5-release</a>  
<a href="http://files.cuba-platform.com/cuba/release-notes/6.5/#studio" target="_blank">studio-6.5-release</a>]]></description>
            <content:encoded><![CDATA[As you already might have noticed we have published the new minor release of CUBA platform and Studio. The new version introduces mostly enhancements of the existing functionality, however, there are a few useful features have been included in 6.5.

This article covers major enhancements of Platform and Studio. The full list of changes is available in the corresponding release notes:

<a href="http://files.cuba-platform.com/cuba/release-notes/6.5/#platform" target="_blank">platform-6.5-release</a>  
<a href="http://files.cuba-platform.com/cuba/release-notes/6.5/#studio" target="_blank">studio-6.5-release</a>

## Contents

[Uber JAR](#uber-jar)  
[Predictive Search UI Component](#predictive-search-ui-component)  
[REST API Versioning](#rest-api-versioning)  
[Load Balancing in Cluster](#load-balancing-in-cluster)  
[ZooKeeper Application Component](#zookeeper-application-component)  
[Polymer UI](#polymer-ui)  
[Bean Validation in CUBA Studio](#bean-validation-in-cuba-studio)  
[Entity Listeners on Groovy](#entity-listeners-on-groovy)  
[Summary](#summary)

## <a id="uber-jar"></a>Uber JAR

Let me start from a very awaiting part, according to the inquiries we get from the community.

Since 6.5 version distribution of your CUBA applications becomes trivial with the support for the Uber JAR feature. Now, you can simply specify configuration in CUBA Studio or your IDE and build JARs in a few clicks.

![text]({{strapiUrl}}/uploads/b71e94604ac744a8ba3d4b4fcf1632bf.gif)

To start the application you only need to run two statements from the command line:

java -jar app-core.jar  
java -jar app.jar

Uber JAR encapsulates all required dependencies as well as a lightweight HTTP Server. More information can be found in <a href="https://doc.cuba-platform.com/manual-6.5/uberjar_deployment.html" target="_blank">this chapter</a> of our documentation.

## <a id="predictive-search-ui-component"></a>Predictive Search UI Component

The collection of visual components is replenished with SuggestionPickerField. The component is designed to perform search in the background and pop-up a list of suggested values while the user input.

![text]({{strapiUrl}}/uploads/7a4c2ce789c8400e8d8c29ebd0f9fa58.png)

The detailed information about the use of _SuggestionPickerField_ is available in the <a href="https://doc.cuba-platform.com/manual-6.5/gui_SuggestionPickerField.html" target="_blank">documentation</a> as well as the link to life demo in the <a href="https://demo.cuba-platform.com/sampler/open?screen=datasource-suggestion-picker-field" target="_blank">Sampler application</a>.

## <a id="rest-api-versioning"></a>REST API Versioning

While the post-delivery support stage it could happen that due to simple refactoring of entities/attributes names the generic REST API cannot be compatible with the old clients (e.g. mobile app) or 3rd party integrations.

The new version has introduced the mechanism of REST request transformation. Now transformation rules can be defined in a simple XML format, explaining the system what naming should be applied over the requests from the old clients.

So, if we rename the _OldOrder_ entity to _NewOrder_ as well as its _date_ attribute to _deliveryDate_ and delete the _discount_ field, using the following transformation XML we can keep compatibility with the clients, which use the old API:

Learn more about this feature in the <a href="https://doc.cuba-platform.com/manual-6.5/rest_api_v2_data_model_versioning.html" target="_blank">documentation</a>.

## <a id="load-balancing-in-cluster"></a>Load Balancing in Cluster

Before 6.5, there were no proper balancing between web and middleware tiers. So, a web block were choosing a middleware server from the list specified in the _cuba.connectionUrlList_ at startup and didn’t change it until it became unavailable.

Now the balancing applies on the level of a user session. A middleware server is being chosen randomly while the first remote connection. An established session is "sticky", so it keeps the same middleware server for its whole life time. If a request is sent from the anonymous session or without any session the "sticky session" approach is not applied and the request goes a random server in the cluster.

In some certain case you might need to define your own balancing rules. Now it can be achieved by providing a custom implementation of the the _cuba_ServerSorter_ bean, which by default, uses the _RandomServerSorter_ class.

## <a id="zookeeper-application-component"></a>ZooKeeper Application Component

With the help of this application component, cluster configuration management is hugely simplified. The component integrates your application with <a href="https://zookeeper.apache.org/" target="_blank">Apache ZooKeepe</a><a href="https://zookeeper.apache.org/" target="_blank">r</a> - a centralized service for maintaining configuration information. The only thing you need to do to manage the cluster topology is to specify the address of ZooKeeper. Since it is done Middleware servers will publish their addresses via the ZooKeeper directory and the discovery mechanisms provided by the application component will request ZooKeeper for addresses of available servers. If a middleware server goes down, it will be automatically removed from the directory immediately or after a timeout.

The source code of the application component is available on <a href="https://github.com/cuba-platform/cuba-zk" target="_blank">GitHub</a> along with documentation available in <a href="https://github.com/cuba-platform/cuba-zk" target="_blank">README</a>. Its binary artifacts are published in the standard CUBA repositories.

## <a id="polymer-ui"></a>Polymer UI

According to the activity on the support forum more and more people have started using our integration with Polymer framework. In this release we have added a few features, intended to make development more straightforward.

First of all, now, when calling an entity instance for editing from a list, it will route you to an editing form, located at another URL. This approach enables the standard browser mechanism of history tracking, so you will be able to move between a list and an editor by clicking the _go back_ and _go forward_ buttons in your browser. Another use of this feature is that you can share a link for some certain entity editor with other users, so they can open this screen directly by calling the link.

Next feature is the _cuba-lookup_ component. It allows users to specify an entity instance for a reference attribute not from dropdown list, but from a popping up screen (lookup screen) with the list of entities. Find more information on this web component <a href="https://cuba-elements.github.io/cuba-elements/components/cuba-ui/" target="_blank">here</a>.

Finally, there is a new element available in the library of visual components for Polymer client. It provides an ability to upload files to the server. Since file is uploaded it will be shown as a clickable link, so users can download it. To learn more about this web component follow <a href="https://cuba-elements.github.io/cuba-elements/components/cuba-file-field/" target="_blank">this link</a>.

## <a id="bean-validation-in-cuba-studio"></a>Bean Validation in CUBA Studio

The bean validation mechanism is now supported from the Studio user interface. So, you can specify constraints over attributes as well as messages to be shown when a value doesn't comply to the constraints.

So, to be sure that a string is a valid email address you just perform a few clicks in the Studio, at it is illustrated in the picture below:

![text]({{strapiUrl}}/uploads/c18e56695e974f1086a6395f3cd669ab.png)

## <a id="entity-listeners-on-groovy"></a>Entity Listeners on Groovy

CUBA Studio now supports scaffolding Entity Listeners in Groovy. Make sure you turned on **Groovy Support** on the **Project properties > Advanced** tab. Since it is on you will be able to choose what language you would prefer to code your Entity Listener.

![text]({{strapiUrl}}/uploads/1adf06f35b1d4b5181d14359de747cef.png)

## <a id="summary"></a>Summary

Traditionally, let me thank all proactive members of our community, who participated the platform development and helped with testing the release candidate version. We keep our eye on the forum to be in time with most required features and benefit our community. You are welcome to watch the <a href="https://vimeo.com/214066066" target="_blank">recorded video</a> of the live webinar session about the release.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's New in CUBA Platform 6.4]]></title>
            <link>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-6-4</link>
            <guid>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-6-4</guid>
            <pubDate>Mon, 06 Feb 2017 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/c126b70cce284f66a676aa5029ec2861.png">The new release of CUBA Platform and CUBA Studio has recently been published. While in version 6.3 we focused on architectural and technical improvements, this release introduces a number of features, that make development faster and more convenient for developers. The new version brings new visual components for the generic user interface, a new mainstream validation mechanism, an engine for an alternative JavaScript front-end generation and other important improvements.

This article covers major enhancements of Platform and Studio. The full list of changes is available in the corresponding release notes:  
<a href="http://files.cuba-platform.com/cuba/platform/platform-6.4-release.html" target="_blank">platform-6.4-release</a>  
<a href="http://files.cuba-platform.com/cuba/studio/studio-6.4-release.html" target="_blank">studio-6.4-release</a>]]></description>
            <content:encoded><![CDATA[The new release of CUBA Platform and CUBA Studio has recently been published. While in version 6.3 we focused on architectural and technical improvements, this release introduces a number of features, that make development faster and more convenient for developers. The new version brings new visual components for the generic user interface, a new mainstream validation mechanism, an engine for an alternative JavaScript front-end generation and other important improvements.

This article covers major enhancements of Platform and Studio. The full list of changes is available in the corresponding release notes:  
<a href="http://files.cuba-platform.com/cuba/platform/platform-6.4-release.html" target="_blank">platform-6.4-release</a>  
<a href="http://files.cuba-platform.com/cuba/studio/studio-6.4-release.html" target="_blank">studio-6.4-release</a>

## Contents

[Studio Templates](#studio-templates)  
[Screen Layout Controls](#screen-layout-controls)  
[Lookup Type](#lookup-type)  
[Value Datasources](#value-datasources)  
[Bean validation](#bean-validation)  
[Cross-Datastore References](#cross-datastore-references)  
[Transaction Listeners](#transaction-listeners)  
[Side Menu](#side-menu)  
[Data Grid](#data-grid)  
[Pivot Table](#pivot-table)  
[Polymer UI](#polymer-ui)  
[Summary](#summary)

## <a id="studio-templates"></a>Studio Templates

![text]({{strapiUrl}}/uploads/80499f1bf0684c15b89ececb8a0bc288.png)

Previously you could use only a few hard-coded screen templates. Now Studio offers an extendable and customizable set of templates for creation of Generic UI screens and Polymer UI components.

You can open the list of Generic UI templates by clicking _New_ on the _Generic UI_ navigator tab, or by selecting an entity and clicking _New_ and then _Generic UI screen_. In the latter case, the list of templates will be filtered and only the templates relevant to the entities will be shown.

You cannot edit templates distributed with Studio, but you can copy them and modify for your needs. So if you want to create a custom template, select a base template and click _Copy template_. Then you will be able to modify the template properties and write code for the screen XML descriptor, controller and localized messages. The template content will be stored in the studio-templates folder of your project and you can commit it to your source code repository.

The same is true for Polymer UI templates, the difference is that the template will contain an HTML file with the Polymer component.

## <a id="screen-layout-controls"></a>Screen Layout Controls

![text]({{strapiUrl}}/uploads/85d9790534ca415e8a84b34b2a8e24c4.png)

Using controls on top of the screen layout designer, you can specify the canvas size or toggle lines designating component borders. If the canvas size is set to absolute values like 1600x900 and the content does not fit, the canvas will display scrollbars.

## <a id="lookup-type"></a>Lookup Type

![text]({{strapiUrl}}/uploads/268cad33e47a4b08859736956e3c4dc3.png)

When defining a reference property, you now can specify how this reference should work in UI. By default, a reference is selected from a lookup screen, but you can also choose the DROPDOWN value to select the reference from a drop-down list, and specify what actions will be present in the PickerField component. This settings affect the following:

*   If the lookup type is set to DROPDOWN, Studio will generate options datasource when scaffolding editor screen. Besides, the Filter component will allow a user to select parameter of this type from a drop-down list instead of lookup screen.

*   If you select certain _Lookup actions_ checkboxes, these actions will be used in a FieldGroup component by default, so you don't have to configure actions in the controller code.

Please note that _Lookup type_ parameter should be set before generation of an entity editor screen.

The lookup type settings are saved in the source code with the help of @LookupType annotation on the entity attribute.

## <a id="value-datasources"></a>Value Datasources

![text]({{strapiUrl}}/uploads/85c9386a0b654aa183336285f3642fe3.png)

Regular collection datasources can load only whole entities, which is fine for CRUD operations. But sometimes you need to display some arbitrary data containing single attributes and aggregates. Previously you had to define non-persistent entities, populate them in custom services and add returned instances to a collection datasource in the screen controller. Now you can use <a href="https://doc.cuba-platform.com/manual-6.4/value_datasources.html" target="_blank">value datasources</a> to execute JPQL queries returning arbitrary results and display these results in standard data-aware visual components.

Value datasources contain instances of the special KeyValueEntity which has no predefined structure. You have to define the structure in the datasource by specifying properties according to the fields returned by your query.

## <a id="bean-validation"></a>Bean validation

<a href="https://doc.cuba-platform.com/manual-6.4/bean_validation.html" target="_blank">Bean validation</a> allows you to define attribute values constraints directly in your entities, and these constraints will be checked by various platform mechanisms, such as data-aware visual components, editor screens and REST API. You can also validate service method parameters and return values.

This feature is based on the JSR 349 - Bean Validation 1.1 and its reference implementation: Hibernate Validator.

## <a id="cross-datastore-references"></a>Cross-Datastore References

![text]({{strapiUrl}}/uploads/571cd0c9bd81455d8c84756195e70549.png)

Now you can create <a href="https://doc.cuba-platform.com/manual-6.4/data_store.html#cross_datastore_ref" target="_blank">relations</a> between entities from different data stores. For example, if your Order entity is stored in the main data store and Customer is in an additional store, Studio will allow you to create an Order.customer many-to-one association attribute. The attribute will be non-persistent, and an additional persistent attribute of the type of Customer's primary key will be automatically added to Order. After that, you can just include the customer attribute in views and connect it to data-aware visual components - the related Customer instance will be saved and loaded from the additional data store.

## <a id="transaction-listeners"></a>Transaction Listeners

<a href="https://doc.cuba-platform.com/manual-6.4/transaction_listeners.html" target="_blank">Transaction listeners</a> allow you to write code that will be executed on transaction commit. Transaction listeners can be used instead of entity listeners when you need to perform some computations using entities of different types. In this case you can consolidate all your logic in one place and achieve better performance.

## <a id="side-menu"></a>Side Menu

![text]({{strapiUrl}}/uploads/f7f32c86a4dc43d1b6e71887061c5c10.png)

<a href="https://doc.cuba-platform.com/manual-6.4/gui_SideMenu.html" target="_blank">SideMenu</a> is a visual component that can be used in the main window to display the main menu of the application. In addition, it has a rich API that allows you to add items, set icons and badges dynamically.

In order to use SideMenu in your project, create a Generic UI screen using the _Side menu main window_ template in Studio.

## <a id="data-grid"></a>Data Grid

<a href="https://doc.cuba-platform.com/manual-6.4/gui_DataGrid.html" target="_blank">DataGrid</a> is a visual component alternative to Table. It has much better performance, especially on large data sets, and provides different ways to display dynamic content. DataGrid is a wrapper around Vaadin's Grid component. We are working on support for all of its native features, as well as providing compatibility with CUBA mechanisms and implementing Table features.

## <a id="pivot-table"></a>Pivot Table

![text]({{strapiUrl}}/uploads/c747ddc2e4424389ad1973020f061b86.png)

<a href="https://doc.cuba-platform.com/charts-6.4/pivotTable.html" target="_blank">PivotTable</a> is a visual component for data analysis. It can display a data set as a summary table or a chart, and it allows a user to restructure data using drag-n-drop. It is based on the JavaScript library <a href="https://github.com/nicolaskruchten/pivottable" target="_blank">github.com/nicolaskruchten/pivottable</a> and can be declared in a screen XML descriptor and connected to a datasource. PivotTable is included to Charts and Maps premium add-on.

## <a id="polymer-ui"></a>Polymer UI

![text]({{strapiUrl}}/uploads/62f419f3b706439e888ff9081769bf38.png)

<a href="https://doc.cuba-platform.com/manual-6.4/polymer_ui.html" target="_blank">Polymer UI</a> is a new way to quickly create front-end portals with mobile-first responsive interface. We recommend to use this technology to create custom and mobile-ready customer-faced front-ends, keeping administrative UI and back-office screens developed using the standard generic user interface as the most efficient and rapid way.

The Polymer UI is based on Google Polymer framework and works with CUBA middleware through the standard REST API. The platform provides the following facilities for Polymer UI portals creation: fully integrated build system, a set of web components for working with CUBA middleware, and Studio templates for easy scaffolding of CRUD web components.

## <a id="summary"></a>Summary

As you see, this release introduces many brand new features. Along with them, we have covered a number of requests and ideas coming from CUBA community through our <a href="https://www.cuba-platform.com/discuss/" target="_blank">support forum</a>. The list of such changes can be found in the platform's <a href="https://youtrack.haulmont.com/issues?q=%23PL+%23STUDIO+Source+link%3A+-%7BNo+source+link%7D+Milestone%3A+%7BRelease+6.4%7D+%23Resolved+" target="_blank">issue tracker</a>. We would like to thank all proactive members of our community, who participated in the platform development and helped with testing the release candidate version.

Finally, you are welcome to watch the recorded video of the live webinar session about the release.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Migrating a Legacy Application to CUBA Platform]]></title>
            <link>https://www.jmix.io/cuba-blog/migrate-lightswitch-application-to-cuba</link>
            <guid>https://www.jmix.io/cuba-blog/migrate-lightswitch-application-to-cuba</guid>
            <pubDate>Thu, 02 Feb 2017 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/7532bd241feb458ebccec79dc3b5fa5b.png">What if you got to the point when your legacy application should be migrated? We decided to provide a step by step guide and show how to migrate a legacy application to CUBA with minimum efforts, taking the official sample for the LightSwitch platform as an example.]]></description>
            <content:encoded><![CDATA[Sometimes it appears that the underlying stack of technologies used for an application is no longer appropriate for further software development and support. It may happen for a big variety of reasons: used technology is old and not supported anymore; legacy application doesn't meet new technical or customer requirements, that are hardly implementable using the old stack; or, finally, you have to support an application developed by a 3rd party company, but don't have enough experience and confidence in the used technology.

So, what if you got to the point when your legacy application should be migrated? We decided to provide a step by step guide and show how to modernize a legacy application with minimum efforts, taking the LightSwitch platform as an example, which has officially been abandoned by Microsoft. CUBA Studio comes along with its migration tool, which streamlines the migration process and makes it very straightforward and transparent. To demonstrate how it works in practice we moved the <a href="https://msdn.microsoft.com/en-us/library/ee256749.aspx" target="_blank">Vision Clinic LightSwitch sample application</a> to CUBA Platform and <b><a href="https://github.com/cuba-platform/cuba-vision-clinic/" target="_blank">described all steps on the official platform GitHub</a></b>.

![text]({{strapiUrl}}/uploads/c0ba384de7ce4864a1f5abe8b4cfeacd.png)

![text]({{strapiUrl}}/uploads/4f1699f695a04f8a935ea8b94aaa9dd5.png)

So, if you are interested in modernization of a legacy application, you are welcome to evaluate the migration facilities of Studio by following the <b><a href="https://github.com/cuba-platform/cuba-vision-clinic/wiki" target="_blank">instructions</a></b>. We are also open for your feedback and ideas of how it can be improved; post your thoughts and questions on the <a href="https://www.cuba-platform.com/discuss/" target="_blank">support forum</a> or discuss it with the community on <a href="https://gitter.im/cuba-platform/cuba" target="_blank">Gitter</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Platform and Studio 6.4 release candidates]]></title>
            <link>https://www.jmix.io/cuba-blog/platform-and-studio-6.4-release-candidates</link>
            <guid>https://www.jmix.io/cuba-blog/platform-and-studio-6.4-release-candidates</guid>
            <pubDate>Thu, 19 Jan 2017 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/0854e60590cb4f3184b80f1e4d45f99e.png">The release candidates of the Platform and Studio version 6.4 are now available.]]></description>
            <content:encoded><![CDATA[The release candidates of the Platform and Studio version 6.4 are now available.

Please take a look at the release notes:  
<a href="http://files.cuba-platform.com/cuba/platform/platform-6.4-release.html" target="_blank">platform-6.4</a>  
<a href="http://files.cuba-platform.com/cuba/studio/studio-6.4-release.html" target="_blank">studio-6.4</a>

and download Studio 6.4:  
<a href="http://files.cuba-platform.com/cuba/studio/6.4.0.RC2/studio-6.4.0.RC2.zip" target="_blank">studio-6.4.0.RC2.zip</a>

We do not recommend using the release candidates in production, but we will highly appreciate if you try them out and send us your feedback via the support forum. The <a href="https://doc.cuba-platform.com/manual-6.4" target="_blank">documentation</a> and release notes are not yet finished, but we will update them in the next few days. The final release is scheduled for the end of January.

Thank you!

**UPDATE 2017-01-27:** RC1 version of the platform and RC2 version of Studio are available. If you have created Polymer client module on the previous RC and want to keep it, please update your code according to the latest <a href="https://github.com/cuba-elements/cuba-app/blob/master/CHANGELOG.md" target="_blank">changes</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[2016: A Game Changing Year for CUBA Platform]]></title>
            <link>https://www.jmix.io/cuba-blog/2016-game-changing-year</link>
            <guid>https://www.jmix.io/cuba-blog/2016-game-changing-year</guid>
            <pubDate>Fri, 06 Jan 2017 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/2af5f1ca4223429381ec7e9cdfacca5b.jpg">The 2016 is just gone, and it was so rich on events for our team, that I decided to recap what happened during it and where it has taken us.]]></description>
            <content:encoded><![CDATA[The 2016 is just gone, and it was so rich on events for our team, that I decided to recap what happened during it and where it has taken us.

Obviously, the main and very challenging change was going open source in April. Now the platform is absolutely free and distributed under Apache 2.0, also there are no runtime restrictions on CUBA applications anymore. Our goal was to free up applications built with CUBA from any runtime license restrictions: we had concerns that the previous license was discouraging too many developers from trying the framework.

Very quickly this proved to be a very positive move. Even though the framework has become absolutely free, the sales of the Premium Add-ons and commercial version of CUBA Studio in April alone exceeded all sales for the previous year, giving us confidence and motivation to develop and professionally support the platform further.  Today we have commercial clients in 33 countries, with Germany, USA and Russia in the lead.

Community growth is impressive as well. Our monitoring tool based on anonymous statistics - thanks to the users who keep this option on - showed over 800 active projects on CUBA Platform in December. This is six times year-on-year growth!

As a result, a handful of messages on the community forum in the beginning of the year has now turned into 20-30 each day. To support the growing community, we introduced regular webinars and trainings, and just a few days ago started Gitter for free chat on platform related topics.

_Active CUBA Platform projects_

![text]({{strapiUrl}}/uploads/ec2fb027c9d94f76a7efee7fa36f3909.png)

_Active projects monthly dynamics_

On the technical side, steered by the community feedback, we focused on making the framework applicable to a wider range of real life use cases, making it more open, more extensible, more scalable. Let me list some of the most important implemented features:

**The CUBA Studio migration tool**. The tool generates data model over an existing database, and as a next step generates CRUD UI based on this model. Needless to say that this greatly simplifies legacy applications migration.

**Jelastic integration.** Now you can deploy CUBA application to the cloud in one click directly from Studio.

**Embedding external UI components**. Vaadin, GWT or arbitrary JavaScript UI components can be easily embedded in your application, and even added to the Studio’s pallette.  

**Multiple datastores**. One the most wanted features - a CUBA application can now talk to multiple databases.

**Application components**. With application components, you can decompose a large application to a set of functional modules and develop them as separate projects. Each of such projects can be deployed separately or combined in a single application. It will likely have its own data model, UI and business logic - following the <a href="http://scs-architecture.org/" target="_blank">Self Contained Systems</a> paradigm.

**New REST API** fully conforming to the REST architectural style: using URIs, HTTP verbs and OAuth2 authentication.

Apart of these, there were numerous improvements in platform releases <a href="https://www.cuba-platform.com/blog/whats-new-in-cuba-platform-6-1-and-studio-2-1" target="_blank">6.1</a>, <a href="http://files.cuba-platform.com/cuba/platform/platform-6.2-changelog.html" target="_blank">6.2</a> and <a href="https://www.cuba-platform.com/blog/whats-new-in-cuba--platform-63/" target="_blank">6.3</a>, and we start 2017 with release 6.4, bringing Polymer client support along with other features.

**  
So - we are looking forward to another great year and I want to say thank you and wish a Happy New Year to all of our community members, whose support and feedback pushes us forward!**]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Roadmap goes Publicly Available]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-and-studio-roadmap-goes-publicly-available</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-and-studio-roadmap-goes-publicly-available</guid>
            <pubDate>Thu, 03 Nov 2016 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/505f98711a0742ec905e54cf6a558f14.png">After a number of requests and continuously coming questions on the future development plans of the CUBA Platform and Studio, finally, we are proud to announce that the roadmap is now available to the community.]]></description>
            <content:encoded><![CDATA[After a number of requests and continuously coming questions on the future development plans of the CUBA Platform and Studio, finally, we are proud to announce that the roadmap is now available to the community.

## How can I Share my Idea?

On our community forum we have a special topic type, where you can share your ideas. Also, you are welcome to vote for the ideas you would like to see in the Platform or Studio soon. Most voted ideas will be considered as highly prioritized candidates to be included in the roadmap.

Since your idea is added to the roadmap it will be linked to a corresponding ticket in our issue tracker, which also becomes available in read-only mode. So you will be able to track an issue history, milestone, fix version and so on.

## How can I See What is Scheduled for the Upcoming Release?

The roadmap is actually a query to YouTrack, that selects important tickets, scheduled for a particular milestone. It is dynamic and can change over time. So, just construct a proper filter to see the features planned for the upcoming release or implemented in one of the previous versions.

Explore the links below to find out about our plans for 6.4 release, which is scheduled for January, 2017:

*   <a href="https://youtrack.cuba-platform.com/issues?q=tag%3A+important+Milestone%3A+%7BRelease+6.4%7D" target="_blank">Important features</a>
*   <a href="https://youtrack.cuba-platform.com/issues?q=project%3A+PL+Milestone%3A+%7BRelease+6.4%7D+" target="_blank">All planned issues in platform</a>
*   <a href="https://youtrack.cuba-platform.com/issues?q=project%3A+STUDIO+Milestone%3A+%7BRelease+6.4%7D" target="_blank">All planned issues in Studio</a>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's New in CUBA Platform 6.3]]></title>
            <link>https://www.jmix.io/cuba-blog/whats-new-in-cuba--platform-63</link>
            <guid>https://www.jmix.io/cuba-blog/whats-new-in-cuba--platform-63</guid>
            <pubDate>Fri, 21 Oct 2016 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/cc7ecd30ac9145e2a4d772afb331ac30.png">We are proud to announce the general availability of the new release of the CUBA Platform and Studio!]]></description>
            <content:encoded><![CDATA[We are proud to announce the general availability of the new release of the CUBA Platform and Studio!  
Perhaps this is one of the most feature-rich platform releases ever - there are important changes on all levels: architecture, extensibility, API usability, and performance.

This article covers major enhancements of the platform. The full list of changes is available in release notes:  
<a href="http://files.cuba-platform.com/cuba/platform/platform-6.3-release.html" target="_blank">Platform 6.3 Release Notes</a>  
<a href="http://files.cuba-platform.com/cuba/studio/studio-6.3-release.html" target="_blank">Studio 6.3 Release Notes</a>

## Contents

[Application Components](#app_components)  
[Support for Multiple Data Stores](#data_stores)  
[Base Entity Classes](#base_entities)  
[Single Sign-On](#sso)  
[Anonymous Usage](#anonymous)  
[New REST API](#rest)  
[Screen Agent](#screen_agent)  
[Query Cache](#query_cache)  
[Summary](#summary)

## <a id="app_components" name="app_components"></a>Application Components

As you know, the platform always had a mechanism of functional decomposition: on one hand, the platform itself is split to the core and add-ons, on the other hand, there was an ability to create extension projects. The mechanism of extensions was limited in that it could work only vertically - you could create a number of extensions for one base project, but you couldn't create an add-on similar to CUBA Reporting or BPM to be combined with other add-ons in a final application and reused in other projects.

Now the problem is solved by introducing the concept of Application Components. With application components, you can decompose a large application to a set of functional modules and develop them as separate projects. Moreover, these modules can be reusable - you can include them to different applications just like you do with CUBA premium add-ons.

For example, in a Taxi management application, the structure of components can be as follows:

![text]({{strapiUrl}}/uploads/38a0d4789d024221a98c749dcd623f53.png)

Here CUBA, Reports and Full-Text Search are the components provided by the platform; Credit Card Payments and Pricing are reusable components working in different applications; Driver Wages contains optional functionality delivered only to certain customers. This optional dependency means that you can include app components in an application not only in development but in the deployment stage too.

Actually, an application component (or app component) is just an application that exposes some information about itself. The information about modules, configuration properties, and artifacts of the component is contained in a special file: <span style="font-family:courier new,courier,monospace">app-component.xml</span>; special JAR manifest entries are used for automatic discovery of components located in the classpath. Application components can also be seen as full-stack libraries: they provide functionality on all levels, including entities, database DDL scripts, middleware services, UI screens and even CSS theming.

Studio enables automatic generation of <span style="font-family:courier new,courier,monospace">app-component.xml</span> for the current project, if you want to make it a component. Just use the link on the **Project properties** tab. In order to use a component in an application, edit **Project properties** and add the component to the **Custom components** list.

You can see an example of creating and using application components in the <a href="https://doc.cuba-platform.com/manual-6.3/app_components_sample.html" target="_blank">documentation</a>.

## <a id="data_stores" name="data_stores"></a>Support for Multiple Data Stores

Until now, the platform mechanisms could work only with a single database selected for an application. You could use other sources of data directly through JDBC or other connections, but it was too complicated to display and edit such "external" data in standard UI components.

The concept of data stores implemented in CUBA 6.3 is designed to solve the problem of working with data from different sources in a single application using the same standard platform mechanisms such as data-aware visual components. A data store is actually an interface with a few methods for loading and saving entities. The platform currently contains one implementation of this interface allowing to work with relational databases through the ORM layer. You can create your own data store implementations in your projects, for example to work with NoSQL databases, in-memory grids, or for integration with other applications.

When you use multiple data stores in an application, its data model will contain entities mapped to data from different locations. If the data store is an RDBMS, the entities will be annotated as JPA persistent classes. Otherwise, the entities will be non-persistent and it will be the responsibility of your custom data store implementation to map the entities to data. An application will always have one "main" data store connected to an RDMS to store platform entities like Users, Roles, Filters, etc. The application entities can be scattered across any number of different stores.

For example, the diagram below represents a structure of data stores for an application that is integrated on the database level with an ERP system, uses MongoDB as a document storage and a REST API to connect to a remote information system. The parts which a native for CUBA a shown in green, the custom parts are in yellow.

![text]({{strapiUrl}}/uploads/2ed9adf6d8b94257a214ea921b8f0310.png)

The mixed data model and custom data stores open the way for creating microservices (or, more specifically, <a href="http://scs-architecture.org" target="_blank">Self-Contained Systems</a>). Suppose you have a Sales application which includes a functionality for managing Customers and Products. You can divide the application into three separate projects: Sales, Customers and Products, each with their own database and UI. In the Sales app, you create two additional data stores for integration with other apps. In the simplest case, the data stores can be the built-in RdbmsStore, so the Sales app will just connect to the other databases. For more loose coupling, you can create custom data stores using REST API and map remote data to non-persistent entities of the Sales data model. As a result, you will have three relatively small self-contained applications: Customers and Products work on their own, Sales contains business logic and UI based on standard CUBA mechanisms but using data from remote systems.

Entities from different data stores now cannot have direct relations. It means that if you want to create a reference to an entity from different store, you have to create a persistent attribute for the ID of the "foreign" entity and a non-persistent attribute for the entity itself, and handle its loading and saving programmatically. In a future platform release, we are going to provide a simple declarative way of linking entities on the application level.

Using Studio, you can quickly configure additional data stores (RDBMS or custom) on the **Advanced** tab of the **Project properties** page.

See the <a href="https://doc.cuba-platform.com/manual-6.3/data_store.html" target="_blank">documentation</a> for the details of data stores configuration.

## <a id="base_entities" name="base_entities"></a>Base Entity Classes

We have refactored <a href="https://doc.cuba-platform.com/manual-6.3/base_entity_classes.html" target="_blank">base classes</a> of entities to make them more lightweight. Now a minimal entity can have only one required system attribute - id, and it can be mapped to almost any database type including IDENTITY. Moreover, composite keys are also supported.

It means that now you can create CUBA entities for almost any existing database without modifying its schema. So for example, your new CUBA application can work with a legacy database simultaneously with a legacy system. It also allows you to integrate with third party systems by connecting their databases as additional data stores.

## <a id="sso" name="sso"></a>Single Sign-On

Single-sign-on (SSO) for CUBA applications allows a user to log in to multiple running applications by entering a single login name and password once in a browser session. This feature is essential for seamless user experience when working with multiple systems. It also helps administrators to manage user passwords in one place when an LDAP integration is not used.

The CUBA SSO requires minimal efforts to set up because any CUBA application can be an Identity Provider (IDP), which is a central element of the SSO infrastructure. All configuration can be done in the deployment stage, so you don't have to worry about it when developing your applications.

![text]({{strapiUrl}}/uploads/8f4881694e194e0a9268d96afc1dda7c.png)

The diagram shows an SSO system with two applications. App 1 is simultaneously an Identity Provider and a Service Provider (i.e. just an application providing some functionality). It contains a special login form shown for all users of the SSO system. App 2 is a Service Provider which redirects users to App 1 IDP for login. User passwords are checked only by IDP, but user roles and permissions are completely separate.

See more information on Single Sign-On in the <a href="https://doc.cuba-platform.com/manual-6.3/sso.html" target="_blank">documentation</a>.

## <a id="anonymous" name="anonymous"></a>Anonymous Usage

Now you can create applications with UI screens available without login. The platform contains a predefined "anonymous" user, so all the application code working before login is executed on behalf of this user. By default, the anonymous user has all permissions, so do not forget to create a role with only required rights before allowing anonymous access.

How it works: there are two top-level windows in an application: login window and main window. The former works for the anonymous user, the latter - for an authenticated user. By default, the login window contains only the login form, but you can add any visual components and datasources to it, or even main window elements, such as WorkArea for opening other screens. In order to create your own login window for anonymous access, go to the **Screens** section in Studio and click **Create login window**.

## <a id="rest" name="rest"></a>New REST API

The first version of the universal REST API, included in the platform for a long time, is not quite RESTful - it's actually a web API providing CRUD and query execution over HTTP. In the platform release 6.3, we are introducing a completely new <a href="https://doc.cuba-platform.com/manual-6.3/rest_api_v2.html" target="_blank">REST API v2</a> which conforms to the REST architectural style: usage of URIs and HTTP verbs, OAuth2 authentication. Together with the improved JSON serialization, the new REST API greatly simplifies the creation of web and mobile client applications.

In addition to CRUD operations with entities, the REST API v2 allows you to execute predefined JPQL queries and invoke service methods. Methods must be explicitly permitted by the developer and can accept and return simple types, entities and POJOs, as well as collections of these types. Such a flexible way of working with services saves you from the creation of Spring MVC controllers just for converting Java types to JSON - this conversion can mostly be done automatically. So you just create regular services on the middleware and register exposed methods in rest-services.xml. After that, you can invoke these service methods from your client passing parameters and receiving results in JSON.

The new REST API also provides endpoints for getting current user details and permissions, the information on the application data model and the machine-readable <a href="http://files.cuba-platform.com/swagger" target="_blank">documentation</a> on the REST API itself.

## <a id="screen_agent" name="screen_agent"></a>Screen Agent

In the new platform version, there is a mechanism that allows you to adapt your UI screens to different devices: desktops, tablets, phones. You just create multiple versions of the screen layout for each supported device, and give them the same ID but different <a href="https://doc.cuba-platform.com/manual-6.3/screen_agent.html" target="_blank">screen agent</a> values. Then at runtime, the platform will choose an appropriate version of the screen depending on the current device from which the user accesses the application.

This simple approach is not truly responsive because the screen will not transform when a user, for example, changes the device orientation. If you don't mind writing CSS with media queries, use <a href="https://doc.cuba-platform.com/manual-6.3/gui_CssLayout.html" target="_blank">CssLayout</a> container for fully responsive screens.

## <a id="query_cache" name="query_cache"></a>Query Cache

A cache is no doubt the most effective performance optimization when you work with a database. And now in addition to the Entity Cache you have a <a href="https://doc.cuba-platform.com/manual-6.3/entity_cache.html" target="_blank">Query Cache</a> with a very simple API. It means that you can just set the cacheable attribute for a datasource, for <span style="font-family:courier new,courier,monospace">LoadContext</span> <span style="font-family:courier new,courier,monospace">Query</span> of for ORM <span style="font-family:courier new,courier,monospace">Query</span>, and the results of this query will be cached and reused next time you execute the query with the same parameters. Of course, a query is evicted from the cache automatically when you update or delete entities of the types used in the query.

Do not forget to set up the Entity Cache for entities, involved in the query caching - the two caches should work together.

## <a id="summary" name="summary"></a>Summary

Concluding this article I would like to notice that the majority of the improvements have been made in response to the real user requests, coming from CUBA community. You are most welcome on our <a href="https://www.cuba-platform.com/discuss/" target="_blank">support forum</a> to share ideas on how we can make the Platform better.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Release candidates of Platform 6.3 and Studio 2.3]]></title>
            <link>https://www.jmix.io/cuba-blog/release-candidates</link>
            <guid>https://www.jmix.io/cuba-blog/release-candidates</guid>
            <pubDate>Mon, 05 Sep 2016 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/05a8d04c82674cd99f8e80efa4825314.png">We are happy to announce the availability of the release candidates of the Platform 6.3 and Studio 2.3 versions!

Please take a look at the release notes:  
<a href="http://files.cuba-platform.com/cuba/platform/platform-6.3-changelog.html" target="_blank">platform-6.3-changelog</a>  
<a href="http://files.cuba-platform.com/cuba/studio/studio-2.3-changelog.html" target="_blank">studio-2.3-changelog</a>]]></description>
            <content:encoded><![CDATA[We are happy to announce the availability of the release candidates of the Platform 6.3 and Studio 2.3 versions!

Please take a look at the release notes:  
<a href="http://files.cuba-platform.com/cuba/platform/platform-6.3-changelog.html" target="_blank">platform-6.3-changelog</a>  
<a href="http://files.cuba-platform.com/cuba/studio/studio-2.3-changelog.html" target="_blank">studio-2.3-changelog</a>

and download Studio 2.3.0.RC2:  
<a href="http://files.cuba-platform.com/cuba/studio/2.3.0.RC2/studio-2.3.0.RC2.zip" target="_blank">studio-2.3.0.RC2.zip</a>  
<a href="http://files.cuba-platform.com/cuba/studio/2.3.0.RC2/studio-2.3.0.RC2.exe" target="_blank">studio-2.3.0.RC2.exe</a>  
<a href="http://files.cuba-platform.com/cuba/studio/2.3.0.RC2/studio-2.3.0.RC2-macosx.dmg" target="_blank">studio-2.3.0.RC2-macosx.dmg</a>

We do not recommend using the release candidates for production, but we would highly appreciate if you try them out and send us your feedback via the support forum. The <a href="https://doc.cuba-platform.com/manual-6.3" target="_blank">documentation</a> and release notes are not yet finished, we will update them in the next few days. The final release is scheduled for the end of September.

Thank you!

**UPDATE 2016-09-30:** RC2 versions of the platform and Studio are available. The final release is expected in the middle of October - we are sorry for the delay.

**UPDATE 2016-10-20**: Final versions of the platform and Studio 6.3 are available!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[One Click Cloud Deployment with Jelastic]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-and-jelastic</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-and-jelastic</guid>
            <pubDate>Wed, 03 Aug 2016 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/f835b661706c4b3f8b387774356f18f5.png">As you may know, CUBA Platform is all about fast web enterprise applications development - achieving this via a combination of pre-built features, extensive scaffolding and visual UI design. However, development is only one part of the project lifecycle, so the platform team took one step further and provided developers with a fully scalable automatic deployment feature.]]></description>
            <content:encoded><![CDATA[As you may know, CUBA Platform is all about fast web enterprise applications development - achieving this via a combination of pre-built features, extensive scaffolding and visual UI design. However, development is only one part of the project lifecycle, so the platform team took one step further and provided developers with a fully scalable automatic deployment feature.

Since release 2.1, CUBA Studio is seamlessly integrated with the <a href="http://jelastic.com/" target="_blank">Jelastic cloud</a> - a multi-cloud PaaS orchestration tool. Jelastic acts as a universal platform abstracting your team from dealing with the specifics of different hosting service providers. This gives you the power to deploy and migrate applications with zero hassle to any of the connected providers worldwide, without building bridges into proprietary APIs. Another unique feature of Jelastic is automatic scaling of resources (cloudlets) your application uses - so you pay only for what you actually use.

To get started you can activate Jelastic account <a href="https://www.cuba-platform.com/cloud" target="_blank">from our website</a> or straight from <a href="https://www.cuba-platform.com/development-tools#cubastudio" target="_blank">CUBA Studio</a> with a participating service provider of your choice. After you set up <a href="https://doc.cuba-platform.com/manual-latest/jelastic_deployment.html" target="_blank">a few parameters</a> in the Studio's _Cloud deployment settings_ page, you're done. Now, invoking _Run > Deploy to cloud_ menu item will build the WAR file and deploy it to the cloud in one click. Java, Tomcat, PostgreSQL or HSQL will already be there. As simple as that!

![text]({{strapiUrl}}/uploads/3469825a3dbd41e5aa2f708be2fdd5a0.png)

Jelastic hosting partners offer CUBA Platform community extended free trial period with more powerful environment - juicy enough to ensure good performance when presenting your prototypes to end-users or your colleagues.

As a summary, this combination of CUBA Platform with Jelastic cloud makes it dead easy to start and test your ideas. <a href="https://www.cuba-platform.com/download" target="_blank">Download Studio</a>, knock up a prototype, deploy to the cloud and get feedback - all in a matter of days, if not hours. And without thinking of hardware or accessibility.

But even when your application is ready to go to production, it still makes good sense to stay with Jelastic. Their cloud service provider community are no amateurs in what they do, offering much more than just bare metal hardware. As an example, <a href="https://mirhosting.com" target="_blank">MIRhosting</a> offers automatic real time synchronization of container hosted data between at least three distributed locations using <a href="https://en.wikipedia.org/wiki/Software-defined_storage" target="_blank">software defined storage</a> technology. Should the main container go down, its replica is automatically started on a different node, providing highest level of failover with absolutely no effort from your side. Meanwhile, <a href="http://www.layershift.com" target="_blank">Layershift</a> offers full SSD powered hardware and a very comprehensive SLA covering all aspects of their service from backups to award winning technical support - all included free.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How Extensible Is Your Framework?]]></title>
            <link>https://www.jmix.io/cuba-blog/integrate-3rd-party-visual-components</link>
            <guid>https://www.jmix.io/cuba-blog/integrate-3rd-party-visual-components</guid>
            <pubDate>Mon, 13 Jun 2016 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/3219075540444fa6922c8e6623f26e1b.png">Attending conferences we always get to meet highly qualified decision makers, who frequently ask the same question: ‘_How open is your framework and what if I need more than you offer out-of-the-box?_‘. The question is very reasonable, as they simply don’t want to be stuck right in the middle of the development curve, then realise  that the framework just doesn’t allow implementing some features or, likely, if you use open source product, it requires an unpredictably long time to dig deeper to poorly documented parts of the framework.

In this article I will illustrate how you can integrate 3rd party visual components into the [CUBA Platform](https://www.cuba-platform.com/).]]></description>
            <content:encoded><![CDATA[Attending conferences we always get to meet highly qualified decision makers, who frequently ask the same question: ‘_How open is your framework and what if I need more than you offer out-of-the-box?_‘. The question is very reasonable, as they simply don’t want to be stuck right in the middle of the development curve, then realise  that the framework just doesn’t allow implementing some features or, likely, if you use open source product, it requires an unpredictably long time to dig deeper to poorly documented parts of the framework.

![text]({{strapiUrl}}/uploads/b8cbffd8facb4e968e77988d7849b1a1.png)

Significant attention is usually paid to the user interface part: how many components does the framework have? Is there an ability to integrate 3rd party widgets? Finally, how easy can those be integrated into your applications.

Even if the framework gives you an enormous number of the components out-of-the-box, occasionally you may need to have something very specific, not generally used, hence, not implemented in the framework.

In this article I will illustrate how you can integrate 3rd party visual components into the CUBA Platform.

## Generic User Interface in the CUBA Platform

To give you a brief idea of what visual components you have out-of-the-box with the CUBA Platform have a look at the pictures below:

![text]({{strapiUrl}}/uploads/739739164c394f0d9d1b5387df3111d2.png)

![text]({{strapiUrl}}/uploads/641e3c527d3e46ed8ae23f8ce8fa57e4.png)

As you see, there is an extensive component set available out-of-the-box, but all of the components are very generic, widely used for enterprise applications. Let’s now assume that we need to integrate something more specific.

From version 2.1 of the CUBA Studio, this process has been massively simplified for Vaadin, JavaScript and GWT components, because the Studio scaffolds stubs and adds all required definitions for a new component. There are three levels of integration of a new component into the platform:

1.  As generic UI of the framework is built over Vaadin, the new component becomes available as a native Vaadin component. Developers can already use this component in CUBA applications, adding it into an unwrapped CUBA container.
2.  The new component is integrated into CUBA Generic UI. In this case, from an application developer perspective, it looks the same as a standard component from the visual components library. The developer can define the component in a screen XML descriptor or create it through _ComponentsFactory_ in a controller.
3.  The new component is available on the Studio components palette and can be used in the WYSIWYG layout editor, as it is shown in the picture below.

![text]({{strapiUrl}}/uploads/5567f655d5f744ae861f133abff02a60.png)

In this article we will have a look at the first level integration for Vaadin component and create a sample application to see how it can be used in your CUBA application at this stage.

## Integrating Vaadin Components

As I previously mentioned, the generic UI in the CUBA Platform is built over the Vaadin framework, it is very easy to integrate its components into your CUBA application:

1.  Add dependency to the 3rd party Vaadin add-on artifact.
2.  Create the **web-toolkit** module in your project. This module contains a GWT widgetset file and allows you to create client-side parts of visual components. Just include the add-on widgetset to the widgetset of your project.
3.  If look and feel of the component does not fit the application theme, create a theme extension and define some CSS for the new component.

Let’s take the [Stepper](https://vaadin.com/directory/-/directory/addon/stepper) component as an example and have a look how it works in the CUBA Studio:

As the first step we click on **Create web toolkit module**, to be able to integrate Vaadin components, then we click on **Create new UI component**:

![text]({{strapiUrl}}/uploads/f297e9ea8c0742acbc328cbad148e668.png)

Now we are about 10 minutes far from having a new Vaadin component in CUBA:

1) Select **Vaadin add-on** in the **Component type** group box.
2) To define **Add-on Maven dependency** value go to the [stepper add-on page](https://vaadin.com/directory#!addon/stepper), press the **Install** green button, copy it from the appearing textbox and paste into the **Add-on Maven dependency** field in the CUBA Studio.

![text]({{strapiUrl}}/uploads/0fa49af8a9b540daad9b7ac70ef708a7.png)

3) The most tricky and confusing part, especially for those who are using Vaadin for the first time, is **Inherited widgetset** (You can learn more about Vaadin WidgetSets [here](https://dev.vaadin.com/wiki/WidgetSet), but you don’t really need to have deep understanding about it to keep going through this article). There is a **Source code** link in the **Related links** section of the [stepper add-on page](https://vaadin.com/directory#!addon/stepper), click on it. The link will lead you to the [GitHub repository](https://github.com/ripla/Stepper/) of the component. To define a widgetset of a Vaadin component you need to find _*.gwt.xml_ file in the sources. Continue to the [_addon/src/main/resources_](https://github.com/ripla/Stepper/tree/master/addon/src/main/resources) folder. Here you see the [org/vaadin/risto/stepper/widgetset](https://github.com/ripla/Stepper/tree/master/addon/src/main/resources/org/vaadin/risto/stepper/widgetset) containing the [StepperWidgetset.gwt.xml](https://github.com/ripla/Stepper/blob/master/addon/src/main/resources/org/vaadin/risto/stepper/widgetset/StepperWidgetset.gwt.xml) file. That’s enough to construct our **Inherited widgetset** value: _org.vaadin.risto.stepper.widgetset.StepperWidgetset_. Simply put, it’s a path to the _*.gwt.xml_ file written as importing class in Java.

![text]({{strapiUrl}}/uploads/d72ac88108a04aca8a65f9c4e67211cd.png)

4) Uncheck the **Integrate into generic UI** box for now and say **OK**.
5) The Studio will show notification “**Component created**” and rebuild the project, because it needs to add new dependency to the gradle build script, download required library and re-compile widgetset. So, we just wait a couple of minutes until the process is finished.
6) As a final touch we adjust the component to fit our application theme.

If we have a look at the [source code](https://github.com/ripla/Stepper/tree/master/addon/src/main/resources/VAADIN/addons/stepper), we can see that this component is _SCSS_ styled, so we need to add its style to the project dependencies. To do so, go to the **Project Properties** section, click **IDE**. IDE will show **build.gradle**, where you should add themes("org.vaadin.addons:stepper:2.3.0") line to the dependencies clause of the configure(webModule) task, as it is shown in the picture below.

![text]({{strapiUrl}}/uploads/ece9ad8fae5f435891eae8ad7ff70957.png)

Now we can apply the styling we want. Go to the **Project Properties** section and click **Create theme extension**. Select **halo**, as the default one, and click **Create**. The Studio will add the _themes/halo/halo-ext.scss_ file in the **web** module of your application, where you can specify styles for new components or modify existing ones. It will also make necessary changes in the build script and recreate project files for your IDE.

![text]({{strapiUrl}}/uploads/a3a2693b74924c97b48c2fe0248facd8.png)

Open the halo-ext.scss file in your IDE and paste the following CSS as it is shown in the picture below:

    @import "../VAADIN/addons/stepper/stepper";
    @include stepper;

    /* Basic styles for stepper inner textbox */
        .stepper input[type="text"] {
           @include box-defaults;
           @include valo-textfield-style;
           &:focus {
             @include valo-textfield-focus-style;
           }
        }

![text]({{strapiUrl}}/uploads/262472cd8d164fd3966d59fbc03d0404.png)

**That’s it! Now we already can use the component in our CUBA application!**

## Using 3rd Party Vaadin Component in your CUBA Application

Let’s finally create a screen with the stepper. As we have completed only the first level of integration it is still not a part of generic CUBA UI, so it cannot be used directly from xml screen descriptor, but it can already be created programmatically.

Let’s get started:

1.  [Download](https://www.cuba-platform.com/) the CUBA Studio from our website, install it, launch CUBA Studio server and open the studio in your browser. If you have any complications at this stage just follow the [video guide](https://www.cuba-platform.com/quickstart) (Part 1 from the Quick Start page).
2.  Create a project named **vaadin-component**. The Studio automatically names project namespace and root package.
![text]({{strapiUrl}}/uploads/85beaeaae6c547979e3a83f15c7a6e37.png)

3.  Follow the steps from the **Integrating Vaadin Components** section.
4.  Since step 3 is completed go to the **Screens** section in the left panel of the Studio, focus on **Web Module** item and click **New**. The Studio will prompt you to choose if you want to create a new screen from scratch or extend an existing screen (e.g. User editor or File Upload dialog). We will go for a new screen **from scratch**.
5.  Let’s now go straight to the **Layout** tab, where we can visually design our screen. We need to use some container, that will act as a placeholder for the stepper. Type ‘_hbox_’ in the component search field, the studio will filter UI components by name. Drag and drop the **HBox** component to the form or the **Hierarchy** section.
![text]({{strapiUrl}}/uploads/365d51e92be7429096f48489fbe2a1da.png)

6.  Right click on the component representation, located in the visual form layout; or select component in the **Hierarchy** section and switch to the **Properties** tab (next to the **Palette** one).

    We will need to use our Hbox from the screen controller, to be able to reach a CUBA component from the controller we will need to define its **id**. Simply press right hand button in the **id** field and the Studio will generate an id automatically.

    Also we would like our stepper to be 250px wide, so we specify this size to its container.

    Apply all the changes we’ve done.
![text]({{strapiUrl}}/uploads/9e91f182474f45bca8516478a64cbe54.png)

7.  Launch your IDE, go to the **Controller** tab of the screen designer and press the **IDE** button. The Studio will generate project files and open the screen controller in your IDE.
![text]({{strapiUrl}}/uploads/e620914abf7a439bbc31017b6a6b9879.png)


8.  Move to the IDE, where we already have our screen controller scaffolded by the Studio. Let’s code a bit. All rows you need to add are annotated with detailed comments:

<div style="overflow-x: scroll;">

package com.company.vaadincomponent.web.screens;

<span class="hljs-keyword">import</span> com.haulmont.cuba.gui.vaadincomponent.AbstractWindow;
<span class="hljs-keyword">import</span> com.haulmont.cuba.gui.vaadincomponent.HBoxLayout;
<span class="hljs-keyword">import</span> com.vaadin.ui.Layout;
<span class="hljs-keyword">import</span> org.vaadin.risto.stepper.DateStepper;

<span class="hljs-keyword">import</span> javax.inject.Inject;
<span class="hljs-keyword">import</span> java.util.Map;

public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Screen</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractWindow</span> </span>{
  <span class="hljs-comment">/* Getting access to the hbox component, using CUBA mechanism for UI components injection */</span>
  @Inject
  private HBoxLayout hbox;

  <span class="hljs-comment">/* Create stepper to be placed into the prepared hbox container */</span>
  private DateStepper stepper = <span class="hljs-keyword">new</span> DateStepper();

  <span class="hljs-comment">/* Overriding init method, which will be called by the framework after creation of all components and before showing the screen */</span>
  @Override
  public <span class="hljs-keyword">void</span> init(<span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Object</span>&gt; params) {
      <span class="hljs-keyword">super</span>.init(params);

      <span class="hljs-comment">/* Unwrapping hbox to get access to the native Vaadin layout to place stepper */</span>
      Layout box = hbox.unwrap(Layout.class);

      <span class="hljs-comment">/* Placing stepper component into the unwrapped hbox container */</span>
      box.addComponent(stepper);

      <span class="hljs-comment">/* Defining stepper size to fit 100% of the parent hbox component width */</span>
      stepper.setWidth(<span class="hljs-string">"100%"</span>);

      <span class="hljs-comment">/* Adding listener to show notification when stepper value is changed */</span>
      stepper.addValueChangeListener(event -&gt;
          showNotification(<span class="hljs-string">"Value has been changed to "</span> + stepper.getValue(), NotificationType.<em>HUMANIZED</em>)
      );
  }
}
</div>

9.  To access our screen from the main menu of the application, go to the **Main Menu** section of the right panel in the Studio, click Edit, focus on the **application** item and press **New**. We left our stepper screen id by default, so, find _screen_ value in the drop down list and press **Add**.
![text]({{strapiUrl}}/uploads/f603e1d014fd42a28416b40b7371ae14.png)

10.  It’s time to launch the application and see how it all works. Press ‘**Play**’ button, which is located right under the **Build** item of the Studio’s main menu. The Studio will ask your permission to update DB, agree on it.

When the application is up and running you will see the [localhost:8080/app](http://localhost:8080/app) link in the bottom-left, click on it.
![text]({{strapiUrl}}/uploads/a1df285110904673a74f87a6783cb189.png)

The CUBA Application will meet you with the login screen, where default user is _admin_, guess what is the password? Just press **Submit**. Click on the **Application -> Screen** item of the main menu and here we go!

![text]({{strapiUrl}}/uploads/bc3ba2d12f73444c99ae58ab548eb8e8.png)

You can find the source code of the working stepper sample project [here](https://github.com/aleksey-stukalov/vaadin-component).

## Conclusion

Also,  I would like to admit that some parts of the process can be hugely simplified and even totally eliminated, but this is the first step that can immediately help users to saturate our generic user interface with rarely used, but sometimes extremely useful widgets. So, if you have suggestions or ideas on how it can be improved, please share them with us on our [forum](https://www.cuba-platform.com/discuss/).]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Meet the CUBA Platform: an Open Source Java RAD Framework]]></title>
            <link>https://www.jmix.io/cuba-blog/open-source-java-rad-framework</link>
            <guid>https://www.jmix.io/cuba-blog/open-source-java-rad-framework</guid>
            <pubDate>Mon, 23 May 2016 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/5a04c58f6a8e4f978b373776cab5ed19.png">Update: After version 7 CUBA was renamed to Jmix, which is effectively 8th major version of the platform.]]></description>
            <content:encoded><![CDATA[Update: After version 7 CUBA was renamed to Jmix, which is effectively 8th major version of the platform.

It has been a year and several important releases since CUBA Platform was presented to the international developers community, so in this article I would like to provide an updated overview, explaining what value it brings to enterprise software developers.

Readers will learn:

- What is CUBA Platform and its architecture?
- What types of solutions CUBA Platform is most efficient at?
- How does the platform cut development time?
- What environments can CUBA applications be deployed to?
- How to migrate a legacy solution to CUBA?
- What is the licensing of the platform and its development tools?

## What is CUBA Platform?

CUBA Platform is an open-source framework intended to streamline the development process of business applications. Such applications will often require complex data models, tens or hundreds of screens, support for running various business processes, strong security requirements and so on.

So, how is CUBA Platform different from tools and frameworks already available out there? The main differentiator is that it is a high-level framework. We've created CUBA on top of the existing stable and battle-proven frameworks and added extra APIs and powerful tools to simplify development. This means that CUBA abstracts developers from underlying technologies — instead of doing routine work using generic frameworks they can focus on the business tasks, empowered by a rich set of built-in features and development tools. At the same time, CUBA does not restrict access to the underlying frameworks, providing the confidence that the resulting application satisfies all the requirements.

## What’s under the hood?

CUBA framework is based on Spring Boot. So, CUBA-based applications inherit all the power of probably the richest ecosystem for enterprise-grade applications.

One of the cornerstones of the framework is metadata — the knowledge of the application data model. All components of CUBA are data-aware. They know everything they need to provide powerful features over the data model: security subsystem, both backoffice and frontend UI, generic REST API, BPM, reporting subsystem and many more other additional modules.

The persistence layer is built over well-known JPA. EclipseLink acts as an ORM framework, as it enables provident data load capabilities. Unlike Hibernate, EclipseLink has a feature of partial load not only for associations fields but also for basic attributes. CUBA introduces DataManager, which is effectively an extension for EntityManager, that applies security permissions and restrictions, enables soft deletion, audit and other useful features targeted to effective and secured data access.

A very important part of the framework is its backoffice UI library. It provides a rich set of data-aware visual components. So, for instance, a table knows it is displaying certain attributes of a driver entity, and a label knows that it is displaying a date. Metadata helps visual components to talk to the data layer via the persistence layer — defining the graph of objects which should be uploaded or updated. This module requires no specific frontend skills for a backend developer — all UI code is written in Java and XML. The built-in component-based UI is declarative: you define screens layout in a visual editor or XML file choosing from the rich set of visual components ranging from all sorts of buttons to Google Maps and dynamic charts. Then you add the initialization and event handling logic in Java controllers. Considering data-aware components, you can create a sophisticated UI very quickly and it will remain easy to maintain, thanks to the clear separation between code and layout. If the choice of available components is not enough, there is a facility to integrate external components and <a href="https://doc.cuba-platform.com/manual-latest/own_component_samples.html" target="_blank">writing your own component</a> is always an option.

![text]({{strapiUrl}}/uploads/d0f40d58f94949b0b2f735fe88494e92.png)

Backoffice UI is an ideal choice for intranet applications and administrative UIs. However, its natural limitations do not allow to develop fancy client-facing frontends. In response to the modern requirements for the user interface, CUBA provides the Frontend UI module, based on ReactJS. CUBA Studio generates <a href="https://github.com/cuba-platform/front-generator" target="_blank">TypeScript SDK generator</a> and React code for the typical set of screens. The SDK provides both data model and application’s service calls that can be used in the front-end codebase.

All user actions are controlled by the security subsystem which is an integral part of the CUBA Platform. The role-based model controls CRUD access down to entity attributes, and even certain screen components or custom tokens that you can use in your code. Row-level security helps to control access to certain data records — for example, users from a regional department will only see documents created by this department. The security settings can be hardcoded in the application or configured at runtime in the UI of your application, so all changes can be done by system administrators on the fly.

![text]({{strapiUrl}}/uploads/2c0662ad30774b6b8a12319de646c7b3.jpg)

In addition to the above, CUBA provides many features. They are either shipped with the framework or can be installed from the <a href="https://www.jmix.io/cuba-platform/marketplace/" target="_blank">marketplace</a> as an add-on. The list of features includes (but not limited to):

- User management and administration tools
- Report management
- Business process management with an integrated visual designer
- Multilanguage interface and multiple timezones support
- Full-text search
- Generic REST API
- LDAP Integration
 
## Where can I deploy my application?

When it comes to the deployment stage and environment options, you have a lot of freedom here. CUBA applications can be deployed in a variety of configurations, starting from a single server running everything, to a highly-available clustered configuration. The platform supports PostgreSQL, Oracle Database, Microsoft SQL Server, MySQL and HSQL (typically used for prototyping) out of the box, and you can switch from one to another as your project grows. It is also important that CUBA applications can be deployed to any Java EE Web Profile server, such as Jetty, Tomcat or Glassfish. Of course, you can encapsulate your application in Docker and/or run it in popular PaaS clouds like Amazon, CloudFoundry, OpenShift or Jelastic.

## Sounds good, so how do I develop CUBA applications?

All you need to develop applications with CUBA Platform is Java SE — which makes your application code more uniform and easier to maintain. This also makes your development team more flexible — you even may not need a subteam of front-end developers or Java EE gurus.

![text]({{strapiUrl}}/uploads/9edcf318df8d49ac8f1a5f51461f8b93.png)

For development, you can use <a href="https://www.jmix.io/cuba-platform/tools/" target="_blank">CUBA Studio</a> - it's an IDE based on IntelliJ IDEA Community Edition, also available as an IDEA plugin. CUBA Studio provides the following functionality:

- enables the visual design of UI and data model
- scaffolds CRUD screens with multiple layout options
- keeps DB up-to-date by automatically generating and running update scripts
- generates stubs for event handlers, services, etc.

The Studio utilizes IDEA's project metamodel, therefore supports code completion as well as component and services injection and many other coding assistance features throughout project's codebase. To boost development productivity even further, the Studio automatically hot deploys all your code except for the data model. Thus, it eliminates a lot of routine work.

If you think of upgrading your legacy system to a modern Java stack, CUBA has an answer for this too. The studio features a migration tool, which will convert a legacy database to CUBA-compliant and automatically generate screens based on the DB schema. Thus you will only need to add custom screens and migrate business logic.

## OK I’m almost convinced... what about licensing?

As stated in the title, the core framework is open source, licensed under Apache 2.0 with its source code available on <a href="https://github.com/cuba-platform/cuba" target="_blank">GitHub</a>. This means that there are no license limitations on the software you develop using CUBA Platform.

CUBA Studio is also free, excluding the following features that are available via commercial subscription:

- visual data model designer
- WYSIWYG screen designer
- visual UI theme editor

Other than these visual editors, there are no limitations in the free version of the Studio. The price of annual per developer subscription starts from just $189 p.a. Even if your subscription is expired, the Studio will remain fully functional and you can continue working with the project codebase.

Hopefully, this overview gives you a good idea of what <a href="https://www.cuba-platform.com/" target="_blank">CUBA Platform</a> is and makes it tempting to try. If so, simply go to the website, <a href="https://www.jmix.io/cuba-platform/tools/" target="_blank">download Studio</a>, pass the <a href="https://www.jmix.io/cuba-platform/learn/quickstart/studio/" target="_blank">Quick Start</a> and have your first CUBA application running in a matter of minutes!

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Platform is Going Open Source]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-is-going-open-source</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-is-going-open-source</guid>
            <pubDate>Thu, 14 Apr 2016 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/04b256cd72b7445aa36f06ce14e96bb6.jpg">The long-awaited moment has come, and now we are happy to announce that the **CUBA Platform has finally joined the free software community**! From now on, all the runtime part of the platform is open source and distributed under the **Apache 2.0** license. This means that you will be able to create and distribute your applications absolutely for free! So, go ahead and start your CUBA application right now!

In this post, I would like to highlight why and how we have changed the licensing track.]]></description>
            <content:encoded><![CDATA[The long-awaited moment has come, and now we are happy to announce that the CUBA Platform has finally joined the free software community! From now on, all the runtime part of the platform is open source and distributed under the Apache 2.0 license. This means that you will be able to create and distribute your applications absolutely for free! So, go ahead and start your CUBA application right now!

In this post, I would like to highlight why and how we have changed the licensing track.

## The Way to Open Source

It’s been half a year since we introduced the CUBA Platform to the international enterprise developers community. In the process of attending conferences and presenting on CUBA to a myriad of audiences, we started to realize the significance of the open source approach for the Java community and how many developers were being excluded from our technology.

I have to say that it has not been an easy decision to take. Looking back, we acknowledge that we even went through the 5 classical stages of acceptance:

*   _Denial_ - licensing policy is great, the community just haven’t fully understood it yet.
*   _Anger_ - why don’t they still understand it? The explanation is so clear on our website!
*   _Bargaining_ - maybe we just need to complement our licensing with something attractive, without changing it?
*   _Depression_ - opensource is not a case for us, because we have to earn money to improve the product, and the current policy is not working. We’re stuck.
*   _Acceptance_ - our focus community requires this change and it works for the most successful players on the market. Finally, after our research, the moment of truth had come and we became convinced that the way to open source is the only right choice!

Нonestly, now we don’t even understand how we could deny an open source approach, because it perfectly corresponds to the main principles in our <a href="https://www.cuba-platform.com/blog/2015-06-29/416" target="_blank">philosophy</a> of being practical and open!

## Where is the Hook?

Most probably you have already raised the natural question about the means of subsistence: How the product can live and be improved upon if it is completely free? Let me explain.

The CUBA Platform itself is a self-sustained full-stack framework, which can be used for a variety of projects. It provides a wide range of enterprise features (security and user management, data-aware UI, generic data filter, scheduled tasks, audit and so on) and ready architecture, including everything a developer would need from DB to UI. All this is now being distributed under the Apache 2.0 license.

But, as you may know, the CUBA Platform is not the only thing we offer to make enterprise application development easier and faster. In addition to the framework, we offer a specialized framework-aware development tool for rapid business application development - CUBA Studio. The CUBA Studio is based in IntelliJ IDEA and provides a convenient and familiar graphical interface to the platform features, so it is possible to create your “Hello world” CUBA application <a href="https://www.jmix.io/cuba-platform/learn/quickstart/studio/" target="_blank">in minutes</a>. The Studio manages many common aspects of enterprise application development: data model creation, visual layout design, source code scaffolding and so on.

The CUBA Studio is free, excluding the following features that are available via commercial subscription: 
*	visual data model designer
*	WYSIWYG screen designer
*	visual UI theme editor

Other than these visual editors, there are no limitations in the free version of the Studio. The price of annual per developer subscription starts from just $389 p.a. Even if your subscription is expired, the Studio will remain fully functional and you can continue working with the project codebase. 

Finally, as a complementary service, we offer trainings and various support level agreements, so that you can start your projects with full confidence and be sure that you will never get stuck facing a technical problem.

As you can see, there are no underwater stones in our new licensing. **The framework itself is absolutely free with its source code on <a href="https://github.com/cuba-platform/cuba" target="_blank">GitHub</a>**, while a few extra features are paid. We believe that it is a good way to contribute to the community and ensure product development at the same time.

## Summary

We are thrilled with this change and hope it will give a powerful impetus to the expansion of our community. We emphasize that we are developer-driven and your feedback is greatly appreciated. So, you are welcome to try the CUBA Platform out and share your experience and ideas with us on our <a href="https://www.cuba-platform.com/discuss/" target="_blank">support forum</a>.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's New in CUBA Platform 6.1 and Studio 2.1]]></title>
            <link>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-6-1-and-studio-2-1</link>
            <guid>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-6-1-and-studio-2-1</guid>
            <pubDate>Sat, 09 Apr 2016 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/41fa8a5a96ba4e2c83c0c934dc1b1711.png">We are proud to announce the general availability of new versions of the CUBA Platform and Studio. The most radical change is licensing - since 6.1 version CUBA is distributed under the Apache 2.0 License. Also, as usual, the new version of the CUBA platform brings in several major new features, along with improvements and bug fixes.]]></description>
            <content:encoded><![CDATA[We are proud to announce the general availability of new versions of the CUBA Platform and Studio.

The major update is the new licensing policy: the main part of the platform is now open source under Apache 2.0 license, the optional components such as BPM, Charts and Maps, Reporting and Full-Text Search are available by per-developer subscription. The CUBA Studio is free for small projects with up to 10 entities and requires the subscription for bigger projects.

The main reason for changing the license is to remove runtime restrictions: now the applications built on the platform are royalty-free, regardless of whether they use free or paid components of the platform.

As usual, the new version of the CUBA platform brings in several major new features, along with improvements and bug fixes. Some of these are listed below.

## Security Improvements

We have greatly improved the row-level security constraints. Now you can define constraints for create/update/delete actions and check constraints in memory for collection attributes. The constraints editor includes a visual tool for easy creation of JPQL and Groovy code fragments by selected entity attributes.

![text]({{strapiUrl}}/uploads/51b88c8c38424b9787bbc8f5af014086.png)

## MySQL Support

The platform now supports MySQL databases out-of-the-box. However, there is an issue with unique constraints for soft-deleted entities: MySQL does not support partial indexes and handles NULLs in indexes in such way that prevents using standard mechanism. See the workaround in the <a href="https://doc.cuba-platform.com/manual-6.1/db_mysql_features.html" target="_blank">documentation</a>.

## Application Properties

Setting values to application properties was always an obscure task, especially for newbies. Where to write a value, how to change it in production? So we moved as many properties as possible to the database and created a special screen to manage them: **Administration > Application Properties**.

Another improvement of application properties mechanism is that you can define or override their values with Java system properties, hence through the command line arguments. It can simplify deployment settings in the cloud.

![text]({{strapiUrl}}/uploads/4a44aa81b4fc4fceb32c2718fb49bf9a.png)

## REST API

The universal REST API is now an independent module and can be used both in web and portal modules. So there is no need to create a separate portal module in your project if you don't want to - just select the **Project properties > Advanced > REST API in web module** checkbox and the REST API will work in your standard web UI module. If you do not use Studio, check out the <a href="https://doc.cuba-platform.com/manual-6.1/rest_api_adding.html" target="_blank">documentation</a> for how to do it manually.

## Stock Charts

We have integrated stock charts from the newest version of AmCharts library.

![text]({{strapiUrl}}/uploads/d72236b1cef74dfdbe3e693a7f4537e8.png)

## CUBA Studio 2.1

### Generate Model from Existing Database

We have eventually implemented the long-awaited feature - support for legacy databases. Studio allows you to generate the data model and standard UI screens from your existing database. It also creates a set of reconciliation scripts that should be run on the database to make it compatible with CUBA entities. This feature greatly facilitates migration from legacy systems: you can create the foundation for the new application in minutes, run it on your real data, and then start implementing your business logic and specific UI using CUBA.

![text]({{strapiUrl}}/uploads/895569be6d7e4f52b0553b6951949ea5.png)

### Extend the CUBA Platform with Your Own Components

When you evaluate a new UI framework, probably one of the first questions that comes to your mind is "What if I need a visual component, that is not currently in the standard list?".

CUBA Studio now allows you to generate the code needed to integrate third-party components distributed as Vaadin add-ons, JavaScript libraries or GWT components. Of course, you can integrate your own components written using these technologies too. Moreover, Studio can show your custom components in the palette and allows a developer to manipulate them in the WYSIWYG layout editor, in the same way through using the standard components. The documentation has a comprehensive <a href="https://doc.cuba-platform.com/manual-6.1/own_component_samples.html" target="_blank">example</a> of using custom UI components in application projects.

![text]({{strapiUrl}}/uploads/9be1f7580ad04bddad84ec91340c8fd7.png)

![text]({{strapiUrl}}/uploads/13789d3cfc6a457eaa998098d4ca9e79.png)

### <a name="cloud-deployment">One-click Cloud Deployment</a>

Studio now enables one-click deployment to the Jelastic cloud. You just create an account on one of the Jelastic hosting providers, then set up the deployment of your project on the **Cloud deployment settings** page in the Studio, and after that, the **Run > Deploy to cloud** menu item allows you to build the WAR file and deploy it to the selected environment.

![text]({{strapiUrl}}/uploads/5b19ec7b8a594eb091f27392d02cd7a8.png)

### Develop CUBA Applications on Groovy

The Studio now simplifies using Groovy in your project. If you select the **Groovy support** checkbox on the **Project properties > Advanced** tab, Studio will add Groovy plugin to your _build.gradle_ and create Groovy source files instead of Java, when screen controllers and service stubs are generated.

The full list of changes in this Studio release can be found <a href="http://files.cuba-platform.com/cuba/studio/studio-2.1-changelog.html" target="_blank">here</a>.

The detailed release notes of CUBA Platform 6.1 are available <a href="http://files.cuba-platform.com/cuba/platform/platform-6.1-changelog.html" target="_blank">here</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How we use Vaadin for our Web Development Tool]]></title>
            <link>https://www.jmix.io/cuba-blog/how-we-use-vaadin-for-our-web-development-tool</link>
            <guid>https://www.jmix.io/cuba-blog/how-we-use-vaadin-for-our-web-development-tool</guid>
            <pubDate>Tue, 09 Feb 2016 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/bba2c914883d4aeea04e8967c1c95079.png">When we started the development of CUBA Studio, we already had built up a large quantity of experience with Vaadin in CUBA Platform, because the generic UI of the platform is also built over this framework. So, why did we choose Vaadin? In this post I will highlight the most valuable features and interesting use cases.]]></description>
            <content:encoded><![CDATA[_Originally posted on Vaadin Blog: <a href="https://vaadin.com/blog/-/blogs/cuba-studio-how-we-use-vaadin-for-our-web-development-tool" target="_blank">https://vaadin.com/blog/-/blogs/cuba-studio-how-we-use-vaadin-for-our-web-development-tool</a>_

<a href="https://www.cuba-platform.com/" target="_blank">CUBA Platform</a> is a fairly new and rapidly growing Java framework for efficient enterprise application development. A significant part of its success can be associated with its own development tool - CUBA Studio, which is Vaadin-faced to the users.

Often, to employ one or another framework, you have to leaf through hundreds of pages before you even get started with the first line in your source code. In order to minimize the barriers to entry for CUBA Platform, we have developed our own framework-aware development tool for rapid business application development - CUBA Studio. CUBA Studio provides a convenient and intuitive graphical interface to any feature of the platform, where you can create your “Hello world” CUBA application in minutes. The studio manages many common aspects of enterprise application development: data model creation, visual layout design, source code scaffolding and so on.

When we started the development of CUBA Studio, we already had built up a large quantity of experience with Vaadin in CUBA Platform, because the generic UI of the platform is also built over this framework. So, why did we choose Vaadin? In this post I will highlight the most valuable features and interesting use cases.

## Pure Java for Complex UI

Since CUBA Studio is a UI-oriented application with a big codebase, it requires good readability and maintainability of its source code. With Vaadin, we can use Java for the entire application. Vaadin makes it possible to use all existing Java libraries from our UI code directly. In addition, Java enables us to inherit and extend the functionality of the framework and third party add-ons. This ability to customize and change the standard behaviour of the components brings flexibility that is fundamental to CUBA Studio.

Thanks to the API of Vaadin, we can code the UI layout simply and quickly, like we use Swing or C# WinForms.

Let’s see how we can create a dialog window of CUBA Studio with Vaadin:

<pre><code class="hljs java"><span class="hljs-keyword">final</span> Window newProjectWindow = <span class="hljs-keyword">new</span> Window();
newProjectWindow.setModal(<span class="hljs-keyword">true</span>);
newProjectWindow.setCaption(<span class="hljs-string">"New project"</span>);
newProjectWindow.setWidth(<span class="hljs-number">400</span>, Unit.PIXELS);

VerticalLayout content = <span class="hljs-keyword">new</span> VerticalLayout();
content.setSpacing(<span class="hljs-keyword">true</span>);

<span class="hljs-comment">// add grid with properties of a new project</span>
GridLayout grid = <span class="hljs-keyword">new</span> GridLayout(<span class="hljs-number">2</span>, <span class="hljs-number">2</span>);
grid.setColumnExpandRatio(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>);
grid.setSpacing(<span class="hljs-keyword">true</span>);
grid.setWidth(<span class="hljs-number">100</span>, Unit.PERCENTAGE);
Label nameLabel = <span class="hljs-keyword">new</span> Label(<span class="hljs-string">"Name"</span>);
nameLabel.setWidthUndefined();
grid.addComponent(nameLabel);

<span class="hljs-comment">// add input controls</span>
TextField nameField = <span class="hljs-keyword">new</span> TextField();
nameField.setWidth(<span class="hljs-number">100</span>, Unit.PERCENTAGE);
grid.addComponent(nameField);
Label versionLabel = <span class="hljs-keyword">new</span> Label(<span class="hljs-string">"Platform version"</span>);
versionLabel.setWidthUndefined();
grid.addComponent(versionLabel);

ComboBox versionBox = <span class="hljs-keyword">new</span> ComboBox();
versionBox.setWidth(<span class="hljs-number">100</span>, Unit.PERCENTAGE);
versionBox.addItem(<span class="hljs-string">"6.0.6"</span>);
versionBox.addItem(<span class="hljs-string">"6.0.5"</span>);
grid.addComponent(versionBox);

<span class="hljs-comment">// add OK and Cancel buttons</span>
HorizontalLayout buttons = <span class="hljs-keyword">new</span> HorizontalLayout();
buttons.setSpacing(<span class="hljs-keyword">true</span>);
buttons.addComponent(<span class="hljs-keyword">new</span> Button(<span class="hljs-string">"OK"</span>));
buttons.addComponent(<span class="hljs-keyword">new</span> Button(<span class="hljs-string">"Cancel"</span>));

content.addComponent(grid);
content.addComponent(buttons);

newProjectWindow.setContent(content);
newProjectWindow.center();
<span class="hljs-comment">// show window</span>
UI.getCurrent().addWindow(newProjectWindow);</code></pre>

Let’s have a look at the result:

![text]({{strapiUrl}}/uploads/17517578afc34b81adfaca24c2d5ef82.png)

This code is very easy to read and modify, because of its homogeneous nature (pure Java) and it does not require HTML markup or CSS styling for the layout of the UI components on a screen.

Have a look at the screen editor in CUBA Studio to see how complex screens can be built using Vaadin. A rich set of UI components within the framework enables us to organize a workspace for our development tool, similar to traditional desktop tools. 

![text]({{strapiUrl}}/uploads/9fae7fd31eb748a083f4074c7ab0dd49.png)

![text]({{strapiUrl}}/uploads/310154281a7a4ffd90d6f6033fb90043.png)

WYSIWYG Screen editor

## Wide Community and Rich Set of Addons

Our choice of Vaadin was also dictated by the large community and the wide range of third party add-on visual components. You can find many useful components using <a href="https://vaadin.com/directory#!browse" target="_blank">Vaadin Addons Directory</a>. Add-ons are easy to add to your Vaadin project, as Maven dependencies, or as a simple jar library. We use a couple of Vaadin add-ons in CUBA Studio. For example, CUBA Studio enables you to scaffold and code sources for entities and screens and services right from your web browser with syntax highlighting. This feature is provided by a Vaadin third party addon - <a href="http://AceEditor" target="_blank">AceEditor</a>. 

![text]({{strapiUrl}}/uploads/62d5500867fc4271a4b3d3c6af6221fe.png)

One more addon we have used in CUBA Studio is <a href="https://vaadin.com/directory#!addon/dragdroplayouts" target="_blank">DragDropLayouts</a>. The Drag-And-Drop approach is used for the WYSIWIG Screen designer, as you can see in the picture below.

![text]({{strapiUrl}}/uploads/7cf89e0d95934f078b371719d8e53029.png)

## Simple Client-Server-Client Communication Using AJAX

Modern web applications should be responsive, fast and user-friendly. Users expect a good reaction on interactions from any IDE. This is very difficult to achieve in a web tool due to the network nature, but we can use PUSH technologies for communication with a server to increase the performance of a web UI. Vaadin enables us to use the WebSocket protocol to organize a client-server communication in case of long background processing. We use this approach a lot, for example, to index a project on Studio startup or during a web server start.

To illustrate the way of how it is used in CUBA Studio, let’s implement a simple handler for the OK button of our “New project” dialog, which executes a fake long operation in the background thread and shows a notification to a user once the long operation is completed:

<pre><code class="hljs java">buttons.addComponent(<span class="hljs-keyword">new</span> Button(<span class="hljs-string">"OK"</span>, <span class="hljs-keyword">new</span> Button.ClickListener() {
&nbsp;&nbsp; <span class="hljs-annotation">@Override</span>
&nbsp;&nbsp; <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buttonClick</span><span class="hljs-params">(Button.ClickEvent event)</span> </span>{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; grid.setEnabled(<span class="hljs-keyword">false</span>);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buttons.setEnabled(<span class="hljs-keyword">false</span>);
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-comment">// you can use ../valo/shared/img/spinner.gif</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newProjectWindow.setIcon(<span class="hljs-keyword">new</span> ThemeResource(<span class="hljs-string">"img/spinner.gif"</span>));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newProjectWindow.setCaption(<span class="hljs-string">"Creating new project ..."</span>);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-keyword">final</span> UI ui = UI.getCurrent();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread projectCreateThread = <span class="hljs-keyword">new</span> Thread(<span class="hljs-keyword">new</span> Runnable() {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-annotation">@Override</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-keyword">try</span> {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-comment">// just emulate long project creation</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(<span class="hljs-number">5000</span>);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <span class="hljs-keyword">catch</span> (InterruptedException ignored) {}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ui.access(<span class="hljs-keyword">new</span> Runnable() {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-annotation">@Override</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newProjectWindow.close();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Notification.show(<span class="hljs-string">"New project has been created"</span>, 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Type.TRAY_NOTIFICATION);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; projectCreateThread.setName(<span class="hljs-string">"AsyncProjectCreate"</span>);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; projectCreateThread.start();&nbsp; 
&nbsp;&nbsp; }
}));</code></pre>

![text]({{strapiUrl}}/uploads/9735277604fb4d8fa62dc13c6225a387.png)

So, you don’t need to write JavaScript code and support all the tricks of different browsers. Read more about PUSH notifications in the <a href="https://vaadin.com/book/-/page/advanced.push.html" target="_blank">Book of Vaadin</a>.

## Conclusion

To sum up, Vaadin became a very good fit for our product. I could go on and on telling you about the features you can get with this framework, but let me just say that “It’s better to see something once, than to hear about it a hundred times” and I invite you all to visit a live demo of <a href="https://demo.cuba-platform.com/studio/" target="_blank">CUBA Studio</a>. The <a href="https://demo.cuba-platform.com/studio/" target="_blank">demo version</a> is available in read only mode. To see the full power of it, you can always <a href="https://www.cuba-platform.com/download" target="_blank">download</a> it from our website.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Our Impression of JavaOne 2015]]></title>
            <link>https://www.jmix.io/cuba-blog/our-impression-of-javaone-2015</link>
            <guid>https://www.jmix.io/cuba-blog/our-impression-of-javaone-2015</guid>
            <pubDate>Sat, 26 Dec 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/a68c5947049a4b00a20542176332aacf.jpg">After an incredibly busy few weeks, we’ve now had time to reflect on the exciting week we spent at JavaOne Conference in San-Francisco. The conference gave insights on where Java community is heading, sparked many ideas for the CUBA Platform and allowed us to meet some outstanding guys, so I decided to share our impressions on the event.]]></description>
            <content:encoded><![CDATA[After an incredibly busy few weeks, we’ve now had time to reflect on the exciting week we spent at <a href="https://www.oracle.com/javaone/index.html" target="_blank">JavaOne Conference</a> in San-Francisco. The conference gave insights on where Java community is heading, sparked many ideas for the CUBA Platform and allowed us to meet some outstanding guys, so I decided to share our impressions on the event.

San Francisco met us with trams, hills and Uber, which is by no surprise absolutely dominant in their home city. A little lifehack - as Uber gives free rides for both first time users and referrals, we got loads of them among six of us ☺.

![text]({{strapiUrl}}/uploads/62be8ba652f54cb38a356d032e98bae7.jpg)

The conference itself is massive! With 9000 attendees and 557 sessions, it is rightfully called the main event in the Java world. The visitors are mainly senior developers and architects, as opposed to some local Java conferences with lower price tags, where you tend to see more younger Java enthusiasts. In the course of conversations at our stand, it turned out that most had experience with enterprise software development.

The central topic of this year's conference was the cloud. Bluemix, OpenShift, Pivotal, Jelastic and others were presented at the expo. Sessions covered various aspects of cloud applications development. Steve Poole raised some interesting questions in his talk, like “If your application is to be run in a dedicated container, do you really need the level of OS abstraction provided by JVM?”

One of our discoveries was a new open source cloud IDE – <a href="https://eclipse.org/che/" target="_blank">Eclipse Che</a>, which provides all the power of desktop IDEs – including refactoring and debugging - in your browser. <a href="https://twitter.com/tylerjewell" target="_blank">Tyler Jewell</a>’s session immediately led to the idea of integrating Eclipse Che with CUBA Studio. As a result, we can get a one-stop web based development environment for the platform, so that CUBA applications can be developed and deployed in the cloud, without need to install any tools locally.

As support for mobile applications development is probably the most anticipated feature of the CUBA Platform, we could not miss the "Back to Mobile: Java 8 on iOS, Android and Windows 10" session by RoboVM guys. RoboVM brings Java 8 and other JVM languages to mobile platforms and enables the sharing of large portions of code between all platforms and the back end, exploiting the full Java ecosystem and reducing cost and time to market. Additionally, RoboVM exposes all platform-specific APIs in idiomatic Java, enabling the creation of truly native mobile apps. Sounds like a good candidate technology for us!

The "Project Jigsaw: Under the Hood" session covered the topics of implementation and usage of the new module system coming in Java 9\. It is no doubt the most interesting feature of the future release, especially from the architecture point of view. Looks like moving the platform to Java 9 will not be easy though - it depends on a stack of third-party libraries, and some will use restricted classes from JDK. On the positive side, it seems like Gradle - which is the core of the CUBA build system - is progressing fast in the modularization direction. The features of the upcoming Gradle release with Java 9 support were discussed during the session “Java Components: Solving the Puzzle with Jigsaw and Gradle”.

We also contributed to the conference program. I explained different approaches <a href="https://www.cuba-platform.com/blog/2015-07-17/421" target="_blank">to off-the-shelf software customization</a> for individual customers, and Yuriy Artamonov held a marathon of three Hands-on Labs, where anyone could build a full featured enterprise application within two hours. If you missed the session you are welcome to follow <a href="http://www.cuba-platform.com/system/files/CUBA%20Hands%20on%20Lab.pdf" target="_blank" >the link</a> and try it on your own.

The Expo Hall hosted 65 exhibitors this year, and our stand was among the busiest – probably partly because we are still a new brand, and partly because accelerating enterprise software development is a vital topic for many of the visitors. No surprise that conversations started with “So, what is the CUBA Platform?”, but after a brief overview, most people were very engaged and stayed for a demo. We did over 400 of those, so half of the team almost lost their voice already by the end of day one ☺. The most frequent request was a tool to run CUBA Platform application and generate CRUD screens on top of an existing database to simplify migration from legacy apps. We have already started working on this, so this is something we will release shortly.

![text]({{strapiUrl}}/uploads/548a6355ae5948dfa0ea3b7cbdf6c060.jpg)

The conference finished with a concert by Elton John and Beck at Treasure Island, and then we took a few days off to make a trip around the amazing California. Catching waves at the Malibu beach, staring at sequoias, sleeping in a tepee, Death Valley hiking – but that’s another story…

![text]({{strapiUrl}}/uploads/b979119e22634eb99151535bd7ebc8ca.jpg)

To conclude this post, I can only thank Oracle for this exceptional event, and we are looking forward to visiting JavaOne 2016!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's New in CUBA Platform 6.0 and Studio 2.0]]></title>
            <link>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-6-0-and-studio-2-0</link>
            <guid>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-6-0-and-studio-2-0</guid>
            <pubDate>Thu, 19 Nov 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/f673a45beb57494b82cf317cc202a674.png">The new version of the CUBA platform has been released, bringing in several major new features, along with a number of bug fixes and improvements.]]></description>
            <content:encoded><![CDATA[The new version of the CUBA platform has been released, bringing in several major new features, along with some improvements and bug fixes.

As this is a major release, there are also some breaking changes listed in the [release notes](http://files.cuba-platform.com/cuba/platform/platform-6.0-changelog.html#6.0.2-breaking). Most of them will be revealed on the compilation of your project, so just follow recommendations listed in the release notes and hints from your IDE. If you have any troubles with the upgrade, feel free to ask us on the [support forum](https://www.cuba-platform.com/support/topics).

The main improvements and enhancements of the 6.0 version are as follows.

## Java 8 Language Features

The platform now requires Java 8 and you can use all its features in the application code: lambdas, streams, etc. We’ve added new listener interfaces suitable for implementation by lambda expressions to Datasource, CollectionDatasource and some other classes. The old interfaces still exist but are deprecated.

![text]({{strapiUrl}}/uploads/4dc30c1746b04b309bb65b5c1db0e3f7.png)

## EclipseLink ORM

EclipseLink 2.6 framework is now used for ORM instead of OpenJPA. It supports the latest JPA 2.1 specification and allows you to use database functions and “on” clause in JPQL. Besides, EclipseLink can be more effective when fetching related collections from the database: see the documentation on view’s fetch attribute.

The whole API for working with data on the EntityManager level has remained the same. The main difference is that now access to an unfetched attribute leads to an exception. Previously you could read unfetched attributes and got nulls, which could result in NullPointerException. We think that the new approach with the definitive exception is better for troubleshooting because the exception tells you what attribute should be included in the view.

Sometimes EclipseLink treats non-trivial JPQL queries differently from OpenJPA, so you may need to modify them if you get exceptions at runtime.

## Security Improvements

We have strengthened control over data sending from middleware to the client tier. First, all attribute permissions are now enforced on middleware and values of hidden attributes are not passed to the client tier. Values of read-only attributes are not saved by DataManager. Second, we removed the ability to load scalar values through DataManager, because it is impossible to check them against entity attribute permissions. So now you cannot execute queries like `select e.name, count(e) from ns$MyEntity e …` through DataManager. If you need such data on the client tier, create a service with appropriate method in your project and protect it with a specific permission if required. If you need just the number of records for certain criteria, use the new `DataManager.getCount()` method. We have also removed the `LoadContext.useSecurityConstraints` attribute which means that if you want to bypass the security constraints from the client tier, you need to create your own service method loading data through EntityManager and returning it to the client.

## Single WAR Deployment

Previously any CUBA application consisted of at least two WAR files (or exploded WARs in the case of fast deployment to Tomcat). This caused unnecessary complication in the deployment of small-scale applications, especially into cloud environments. Now you can create a single WAR file containing both client tier and middleware, which makes the deployment process trivial.

## Upgraded Dependencies

The new platform release is based on the latest versions of underlying frameworks and tools:

*   Spring Framework 4.2.0
*   Vaadin 7.5.6
*   AmCharts 3.17.1
*   Lucene 5.3.0
*   Gradle 2.6
*   Tomcat 8

We have changed the logging API to SLF4J and implementation to Logback 1.1.3\. But your application can still use Commons Logging or Log4j API thanks to the bundled log4j-over-slf4j bridge.

## CUBA Studio 2.0

We have created the new simplistic visual theme for Studio, so now it looks really cool. The new Studio user interface is based on Vaadin 7 and supports proper scaling when using the browser zoom function.

![text]({{strapiUrl}}/uploads/57743a5acf1a4840b6798c52489a499d.png)

The main functionality improvement is the advanced settings for standard screens creation. Now you can create both browser and editor screens as before, or only one of them, or even combine the browser and the editor on one screen where the table is on the left side, and edit fields for the selected record are on the right side. The settings also allow you to choose what components will be added to the generated screens.

![text]({{strapiUrl}}/uploads/044b232004e44387b10cafedd9ce619a.png)

The full list of changes in this Studio release can be found [here](http://files.cuba-platform.com/cuba/studio/studio-2.0-changelog.html).

The detailed release notes of CUBA Platform 6.0 are available [here](http://files.cuba-platform.com/cuba/platform/platform-6.0-changelog.html).]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Platform at the Gartner Symposium]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-at-the-gartner-symposium</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-at-the-gartner-symposium</guid>
            <pubDate>Thu, 22 Oct 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/d61d56e0a83b48098b7f7b3d0a8af06b.png">Haulmont Technology has been selected by Gartner to exhibit as an ‘Emerging Technologies Exhibitor’ at the Gartner Symposium, the world's most important gathering of CIOs and senior IT executives, taking place 8th - 12th November in Barcelona.]]></description>
            <content:encoded><![CDATA[<img style="float: right; margin-bottom:7px;" src="{{strapiUrl}}/uploads/4dc545e609aa4cc6a73e1d02c91edce8.png">

Haulmont Technology has been selected by Gartner to present CUBA Platform as an ‘Emerging Technologies Exhibitor’ at the Gartner Symposium, the world's most important gathering of CIOs and senior IT executives, taking place 8th  - 12th November in Barcelona.

We will also present a session in the Emerging Tech Theatre, titled ‘Harnessing DevOps as a competitive advantage in the new digital enterprise’. The presentation will describe world examples of DevOps that yield commercial benefits and feature case studies from companies using business process automation, dynamic scheduling and smart decision-making systems to drive growth.

For further information please visit <a href="http://www.gartner.com/events/emea/barcelona-symposium" target="_blank">the conference website</a>. Haulmont’s presentation takes place in ET8 at 18:30-18:45 on Tuesday November 10th.

]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Major Release of the CUBA Platform is Coming]]></title>
            <link>https://www.jmix.io/cuba-blog/major-release-of-the-cuba-platform-is-coming</link>
            <guid>https://www.jmix.io/cuba-blog/major-release-of-the-cuba-platform-is-coming</guid>
            <pubDate>Wed, 07 Oct 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/667477306bfc42c4973216debcdd646d.png">We are happy to announce the new release of the CUBA Platform is getting closer, with only a couple of weeks until the release, let’s take a look at what will the new version bring.]]></description>
            <content:encoded><![CDATA[We are happy to announce the new release of the CUBA Platform is getting closer, with only a couple of weeks until the release, let’s take a look at what will the new version bring.

## Java 8

Firstly, the platform will support the newest version of Java. Consequently, all the features, bells and whistles of Java 8 will be available for your CUBA applications.

With the new version you will be able to extensively use Lambda Expressions, Method References, Stream API and other Java 8 features.

## Eclipse Link

As you may know, CUBA currently employes OpenJPA as an ORM engine, but due to OpenJPA not supporting the latest JPA specification, OpenJPA will be substituted with EclipseLink. The new ORM, EclipseLink, will enable JPA 2.1 standard and allow the CUBA Platform to evolve further.

EclipseLink enables you to use database functions in JPQL and calling stored procedures, as well as gives you more control when loading object graphs. These powerful features will allow you to improve the performance of database operations.

## aPaaS

Deployment to aPaaS cloud providers is impressively simplified. You can now deploy and run your CUBA application in popular aPaaS: IBM Bluemix, Pivotal Cloud Foundry or RedHat OpenShift.

## The CUBA Studio

Thank you for your recent feedback, from this the CUBA Studio now brings a number of further improvements:

*   The visual scaling has been improved when using the browser zoom function
*   More options of the standard (CRUD) screens auto-generation have been added
*   <span style="font-size: 15px;">The screen designer layout has been improved</span>
*   <span style="font-size: 15px;">The new dark visual theme is now available and the light theme is coming soon</span>

This is just the beginning, the full list of changes will be available with the platform when the new version is released.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's New in CUBA Platform 5.6 & Studio 1.6]]></title>
            <link>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-5-6-and-studio-1-6</link>
            <guid>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-5-6-and-studio-1-6</guid>
            <pubDate>Mon, 07 Sep 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/fa857a62bd6b4df19e65a9392efcfd6e.png">The new version of the CUBA platform has been released, bringing in several major new features, along with a number of bug fixes and improvements.]]></description>
            <content:encoded><![CDATA[The new version of the CUBA platform has been released, bringing in several major new features, along with a number of bug fixes and improvements.

The main improvements and enhancements of the 5.6 version are as follows.

## Business Process Management

The new Business Process Management (BPM) subsystem allows you to create and run BPMN (Business Process Management Notation) 2.0 business processes. It has most of the features available in our Workflow subsystem, such as the visual process designer and tight integration with application screens and the data model. The obvious advantage over the old Workflow subsystem is the adherence to the modern and widely used BPMN 2.0 standard. Now your business analysts are able to create processes using the familiar notation, and then simply import them into the CUBA-based application and run with minimum of modifications.

Example of a process design:

![text]({{strapiUrl}}/uploads/b36f5b53faf64f248fd91efc6429a6bd.png)

The process instance screen enables generic process control, such as taking process actions, managing actors and attachments:

![text]({{strapiUrl}}/uploads/c8664d2dec57404486b4cd2f9eb4ea00.png)

The BPM base project is intended to be an alternative to the old Workflow mechanism and <span style="font-size: 15px;">should be used in all new projects instead of Workflow. Detailed documentation is available</span> <a href="http://docs.cuba-platform.com/cuba/5.6/bpm/en/html-single/bpm.html" target="_blank">here</a><span style="font-size: 15px;">.</span>

## Report Output to Chart

If your application project employs both **reports** and **charts** base projects, you can create reports that are displayed in a special Chart screen inside of your web application. This screen can be opened from any application screen via RunReportAction or from the main menu **Reports > Show Charts**.

Example of the Chart screen:

![text]({{strapiUrl}}/uploads/490d6c5b96a4493b96283d3894e045fa.png)

A report data structure is defined as usual and can contain queries in SQL, JPQL or Groovy:

![text]({{strapiUrl}}/uploads/9ee8667328814c32a6a82fc9f510d928.png)

Chart template editor allows you to define the chart type (pie or serial), link chart axes to band fields and specify additional visualization parameters:

![text]({{strapiUrl}}/uploads/a6fdf0ec35db428695f5a126911a9b2e.png)

## Other Platform Improvements

The _CellClickListener_ and _PlainTextCell_ interfaces allow you to improve performance of the Table component by eliminating the need to create heavy-weight components inside generated cells.

In the Filter component, a desired table page size is now selected from the drop-down list with the predefined set of values, which is more convenient than before.

The **Data Recovery** screen now restores the whole graph of entities deleted by cascade relations. For example, if you delete a Role with Permissions, after restoring the Role the Permissions will also be restored automatically.

## CUBA Studio 1.6

The new Studio release introduces the Full-Text Search configuration editor. If you use the **fts** base project for your CUBA application then the **Main menu** navigator section will be changed to **Other**. This new section provides access to the fts.xml editing page:

![text]({{strapiUrl}}/uploads/cdcb69bd0d08402d8a6a9201d2fdd83e.png)

Moreover, when you create new entities, Studio adds them to the FTS configuration with default settings.

The detailed release notes of CUBA Platform 5.6 are available <a href="http://files.cuba-platform.com/cuba/platform/platform-5.6-changelog.html" target="_blank">here</a>.

The full list of changes in this Studio release can be found <a href="http://files.cuba-platform.com/cuba/studio/studio-1.6-changelog.html" target="_blank">here</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Yet Another Report Generator?]]></title>
            <link>https://www.jmix.io/cuba-blog/report-generator</link>
            <guid>https://www.jmix.io/cuba-blog/report-generator</guid>
            <pubDate>Tue, 01 Sep 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/bad7291d28514ed3b468d9a9557750bf.png">If you have experience of business application development, then most likely you will have encountered a requirement for the application to have a flexible reporting mechanism. The company I work for is mainly focused on developing business solutions and reporting is an essential, indeed, must have aspect of all the enterprise systems we develop. To enable flexible reporting in our systems, we have developed our own **open-source** (distributed under **Apache 2.0 license**) report generator - [YARG](https://github.com/cuba-platform/yarg) (Yet Another Report Generator).]]></description>
            <content:encoded><![CDATA[If you have experience of business application development, then most likely you will have encountered a requirement for the application to have a flexible reporting mechanism. The company I work for is mainly focused on developing business solutions and reporting is an essential, indeed, must have aspect of all the enterprise systems we develop. To enable flexible reporting in our systems, we have developed our own **open-source** (distributed under **Apache 2.0 license**) report generator - [YARG](https://github.com/cuba-platform/yarg) (Yet Another Report Generator). Now YARG is a heart of the reporting in the [CUBA platform](https://www.cuba-platform.com/) - which itself is the basis of all the systems we develop.

## Why is There a Need to Develop a New One

<span style="font-size: 15px;">First of all, let me remark that we are not wheel reinventors. We are always looking for solutions to integrate with, as long as those solutions fit us. Unfortunately, in this case we couldn’t find any open source tool that met the following requirements we identified:</span>

*   Generate report in template format and/or convert the output to _PDF_
*   Avoid use of external tools for report template creation (Microsoft Office or Libreoffice should be enough)
*   Support various formats of templates: _DOC, ODT, XLS, DOCX, XLSX, HTML_
*   Ability to use complex _XLS_ and _XLSX_ templates with charts, formulas and etc.
*   Ability to use _HTML_ layout and insert/embed images
*   Split out data layer (report structure and data fetching) and presentation layer (report templates)
*   Enable various methods of data fetching such as _SQL_, _JPQL_ or _Groovy_ script
*   Ability to be integrated with IoC frameworks (_Spring, Guice_)
*   Functionality to use the tool as a standalone application, to be able to use it bеyond of the Java ecosystem (e.g. to generate reports using _PHP_)
*   Store report structure in a transparent _XML_ format

The closest tool we could find was JasperReports, but there were a few blockers which stopped us from using it:

*   The free version could not generate DOC reports (there was a commercial library which provided this functionality)
*   XLS reports were very limited, and it was not possible to use charts, formulas and cell formatting
*   To create a report, it is necessary to have a certain skillset and knowledge of how to use very specific tools (e.g. iReports)
*   There is no clear separation between data and presentation layers

Of course we researched lots of other different tools, but all other libraries we found were focused on some specific format. We wanted to have a panacea for reporting - one tool for all kind of reports.

Taking in consideration all the points and thoughts listed above, we decided to develop another, but bespoke tool for report generation.

## What’s Under the Hood

When we started YARG it was not a problem to find a library for _XLS_ integration (_POI-HSSF, JXLS_, etc.). We decided to go for _Apache POI_ as the most popular and well supported library.

The situation around _DOC_ integration was completely the opposite. Only a very few options were available in the open-source market (_POI-HWPF, COM_ and _UNO Runtime_). The _POI-HWPF_ library was very limited in a number of ways and we did not consider it as a suitable option. We had to choose between _COM_ and _UNO Runtime_, which is literally an API for the OpenOffice server side integration.

So, after deep investigation we decided to pick _UNO Runtime_, mainly because of the positive feedback from people who successfully employed it for systems coded in completely different languages, such as _Python_, _Ruby_, _C#_, etc.

While use of _POI-HSSF_ was quite straightforward (except of charting), we faced a number of challenges integrating _UNO Runtime_:

*   There is no clear API to work with tables
*   Each time a report is generated, _OpenOffice_ starts. Initially we used _bootstrapconnector_ to manage _OpenOffice_ processes, but later it became clear that in many cases it doesn’t kill the process after a report is generated. Thus, we had to re-implement the logic of _OpenOffice_ start and shutdown (thanks to _jodconverter_ developers, who pointed many good ideas on this matter)
*   Also _UNO Runtime_ (and OpenOffice Server itself) has significant problems with thread-safety and this can lead to the server freezing or terminating itself if an internal error occurs. To overcome this, we had to implement a mechanism to restart reports if the server fails, with an obvious detrimental consequence for performance

<span style="font-size: 15px;">Later on, when the _DOCX4J_ library became very mature and popular, we supported _XLSX/DOCX_. The main advantage of the DOCX4J library is that it provides the necessary low level access to the document structure (basically, you operate with _XML_). Another benefit of using _DOCX4J_ is that it doesn’t require _OpenOffice_ server integration for _DOCX_ reports generation.</span>

Also, there is an ability to use document with Freemarker markup as a report template. We usually use it to generate very custom reports as HTML and then convert the result to PDF.

Finally, YARG infrastructure is developed in an extendable way, so that experienced users can implement integration with any other template type by themselves.

## Hello World Report

Let’s get to know YARG. The main idea of the report generator is to split out the data layer and presentation layer. The _Data Layer_ enables scripting or direct _SQL_ querying to fetch the desired information and the presentation layer represents the markup of the fetched data.

All YARG reports consist of so-called ‘_Bands_’. A _Band_ is something that links up data and presentation layers together. So, every band knows where to get the data from and where it is placed in the template.

For example, we want to print out all our employees to an Excel spreadsheet. We will need to create the ‘_Staff_’ band and define an _SQL_ query to fetch the list of the employees:

    select name, surname, position from staff

#### **Java Code**

    ReportBuilder reportBuilder = new ReportBuilder();
    ReportTemplateBuilder reportTemplateBuilder = new ReportTemplateBuilder()
            .documentPath("/home/haulmont/templates/staff.xls")
            .documentName("staff.xls")
            .outputType(ReportOutputType.xls)
            .readFileFromPath();
    reportBuilder.template(reportTemplateBuilder.build());
    BandBuilder bandBuilder = new BandBuilder();
    ReportBand staff= bandBuilder.name("Staff")
            .query("Staff", "select name, surname, position from staff", "sql")
            .build();
    reportBuilder.band(staff);
    Report report = reportBuilder.build();

    Reporting reporting = new Reporting();
    reporting.setFormatterFactory(new DefaultFormatterFactory());
    reporting.setLoaderFactory(
            new DefaultLoaderFactory().setSqlDataLoader(new SqlDataLoader(datasource)));

    ReportOutputDocument reportOutputDocument = reporting.runReport(
            new RunParams(report), new FileOutputStream("/home/haulmont/reports/staff.xls"));

The only thing left is to create the _XLS_ template:

![text]({{strapiUrl}}/uploads/5f9968048ba74ea6985ebb0b66895f7d.png)

Here we go! Just run the program and enjoy the result!

## Advanced Example without Java

Let’s assume we have a network of bookshops. There is a need to generate an _XLS_ report showing the list of sold books, with reference to the bookshop where the books were sold. Moreover, we don’t have a Java developer, only a system administrator with the basic skill set of _XML_ and _SQL_.

First of all we need to create an _XLS_ template for the report:

![text]({{strapiUrl}}/uploads/d3b9c6d5719949f8a7459461fb69d624.png)

As you can see, we define two named regions (corresponding to the bands): for shops (in blue) and for book instances (in white).

Now we have to fetch required data from the database:

    select shop.id as "id", shop.name as "name", shop.address as "address" 
    from store shop

    select book.author as "author", book.name as "name", book.price as "price",  count(*) as "count" 
    from book book where book.store_id = ${Shop.id} 
    group by book.author, book.name, book.price

Finally, we declare the bands structure of the report using _XML_:
<br>
```java
<?xml version="1.0" encoding="UTF-8"?>
<report name="report">
    <templates>
        <template code="DEFAULT" 
			documentName="bookstore.xls" 
			documentPath="./test/sample/bookstore/bookstore.xls" 
			outputType="xls" 
			outputNamePattern="bookstore.xls"/>
    </templates>
    <rootBand name="Root" orientation="H">
        <bands>
            <band name="Header" orientation="H"/>
            <band name="Shop" orientation="H">
                <bands>
                    <band name="Book" orientation="H">
                        <queries>
                            <query name="Book" type="sql">
                                <script>
                                    select 
                                    	book.author as "author", 
                                    	book.name as "name", 
                                    	book.price as "price",  
                                    	count(*) as "count" 
                                    from book  
                                    where book.store_id = ${Shop.id} 
                                    group by book.author, book.name, book.price
                                </script>
                            </query>
                        </queries>
                    </band>
                </bands>
                <queries>
                    <query name="Shop" type="sql">
                        <script>
                            select 
                            	shop.id as "id", 
                            	shop.name as "name", 
                            	shop.address as "address" 
                            from store shop
                        </script>
                    </query>
                </queries>
            </band>
        </bands>
        <queries/>
    </rootBand>
</report>
```

<p>Let’s launch the report and have a look at the result (how to run a report is described below in <strong>Standalone</strong> section):</p>

![text]({{strapiUrl}}/uploads/b1eacfd451a44ed7a0f6a0fa926811a4.png)

<p>This use case shows that you can have a reference to the parent band: <code class="sql">book.store_id = ${Shop.id}</code>. This allowed us to filter the books sold by each particular bookshop.</p>

<h2>One More Advanced Example</h2>

<p>Let’s now create an invoice report. We will create a <em>DOCX </em>document and then convert to the immutable form - <em>PDF </em>document. To illustrate another way of how to load data, we will use <em>Groovy </em>script, instead of the direct <em>SQL</em> query:</p>

```java
<?xml version="1.0" encoding="UTF-8"?>
<report name="report">
    <templates>
        <template code="DEFAULT" 
		documentName="invoice.docx" 
		documentPath="./test/sample/invoice/invoice.docx" 
		outputType="pdf" 
		outputNamePattern="invoice.pdf"/>
    </templates>
    <formats>
        <format name="Main.date" format="dd/MM/yyyy"/>
        <format name="Main.signature" format="${html}"/>
    </formats>
    <rootBand name="Root" orientation="H">
        <bands>
            <band name="Main" orientation="H">
                <queries>
                    <query name="Main" type="groovy">
                        <script>
                            return [
                              [
                               'invoiceNumber':99987,
                               'client' : 'Google Inc.',
                               'date' : new Date(),
                               'addLine1': '1600 Amphitheatre Pkwy',
                               'addLine2': 'Mountain View, USA',
                               'addLine3':'CA 94043',
                               'signature':<![CDATA['<html><body><b>Mr. Yarg</b></body></html>']]]]><![CDATA[>
                            ]]
                        </script>
                    </query>
                </queries>
            </band>
            <band name="Items" orientation="H">
                <queries>
                    <query name="Main" type="groovy">
                        <script>
                            return [
                                ['name':'Java Concurrency in practice', 'price' : 15000],
                                ['name':'Clear code', 'price' : 13000],
                                ['name':'Scala in action', 'price' : 12000]
                            ]
                        </script>
                    </query>
                </queries>
            </band>
        </bands>
        <queries/>
    </rootBand>
</report>
```

<p>As you may have noticed, <em>Groovy</em> script returns <code class="java">List&lt;Map&lt;String, Object&gt;&gt;</code> object. So, each item is represented as a <em>Key</em> (parameter name) and <em>Value</em> (parameter value).</p>

<p>As a finishing touch we will need to create a&nbsp;<em>DOCX</em>&nbsp;template:</p>

![text]({{strapiUrl}}/uploads/0d331da4412e46bd82f11a9f79170dbc.png)

To link the bottom table to the list of of books we use <code class="java">##band=Items</code> marker.</span>

<p>After the report is generated we get the following output:</p>

![text]({{strapiUrl}}/uploads/a44cdd12debb4189ad15517981e08dcf.png)

<h2>IoC Frameworks Integration</h2>

<p>As mentioned before, one of the requirements was to provide an ability to integrate into IoC frameworks (<em>Spring, Guice</em>). We use YARG as a part of the powerful reporting engine in the CUBA platform - our high level Java&nbsp; framework for enterprise applications development. CUBA employs <em>Spring</em> as IoC mechanism, let’s have a look how YARG is integrated into the platform:</p>

```java
<bean id="reporting_lib_Scripting" 
	  class="com.haulmont.reports.libintegration.ReportingScriptingImpl"/>
<bean id="reporting_lib_GroovyDataLoader" 
	  class="com.haulmont.yarg.loaders.impl.GroovyDataLoader">
    <constructor-arg ref="reporting_lib_Scripting"/>
</bean>
<bean id="reporting_lib_SqlDataLoader" 
	  class="com.haulmont.yarg.loaders.impl.SqlDataLoader">
    <constructor-arg ref="dataSource"/>
</bean>
<bean id="reporting_lib_JpqlDataLoader" 
	  class="com.haulmont.reports.libintegration.JpqlDataDataLoader"/>
<bean id="reporting_lib_OfficeIntegration"
      class="com.haulmont.reports.libintegration.CubaOfficeIntegration">
    <constructor-arg value="${cuba.reporting.openoffice.path?:/}"/>
    <constructor-arg>
        <list>
            <value>8100</value>
            <value>8101</value>
            <value>8102</value>
            <value>8103</value>
        </list>
    </constructor-arg>
    <property name="displayDeviceAvailable">
        <value>${cuba.reporting.displayDeviceAvailable?:false}</value>
    </property>
    <property name="timeoutInSeconds">
        <value>${cuba.reporting.openoffice.docFormatterTimeout?:20}</value>
    </property>
</bean>
<bean id="reporting_lib_FormatterFactory"
      class="com.haulmont.yarg.formatters.factory.DefaultFormatterFactory">
    <property name="officeIntegration" ref="reporting_lib_OfficeIntegration"/>
</bean>
<bean id="reporting_lib_LoaderFactory" class="com.haulmont.yarg.loaders.factory.DefaultLoaderFactory">
    <property name="dataLoaders">
        <map>
            <entry key="sql" value-ref="reporting_lib_SqlDataLoader"/>
            <entry key="groovy" value-ref="reporting_lib_GroovyDataLoader"/>
            <entry key="jpql" value-ref="reporting_lib_JpqlDataLoader"/>
        </map>
    </property>
</bean>
<bean id="reporting_lib_Reporting" class="com.haulmont.yarg.reporting.Reporting">
    <property name="formatterFactory" ref="reporting_lib_FormatterFactory"/>
    <property name="loaderFactory" ref="reporting_lib_LoaderFactory"/>
</bean>
```

<p>In order to integrate YARG into <em>Spring Framework</em> the following beans should be registered:</p>

<ul style="margin-left: 40px;">
	<li><code class="xml">reporting_lib_Reporting</code> - provides an access to the core report generation functionality. The <code class="xml">reporting_lib_FormatterFactory</code> - manages the output to different formats (<em>DOCX, XSLX, DOC</em>, etc.)</li>
	<li><code class="xml">reporting_lib_LoaderFactory</code> - provides the data load functionality (contains a number of beans corresponded to different sources)</li>
	<li><code class="xml">reporting_lib_OfficeIntegration</code> - integrates report generator with the OpenOffice server (required for <em>DOC</em> and <em>ODT</em> reports generation)</li>
</ul>

<p>As you can see YARG can be easily embedded within your application.</p>

<h2>Standalone Use</h2>

<p>Another valuable feature of YARG, is that it can be used as a standalone application. Technically, if you have JRE installed, you can run the report generator from the command prompt. For instance, if you have a server side PHP application and want to enable reporting in your application, then just create an XLS template, declare the report structure in XML and launch YARG from the command prompt:</p>

```java
yarg -rp ~/report.xml -op ~/result.xls “-Pparam1=20/04/2014”
```
<h2>More Features Available with the CUBA platform</h2>

<p>YARG is deeply integrated into the CUBA platform and acts as the core engine for the powerful reporting mechanism implemented in the platform.</p>

<p>First of all, you can embed the reporting in one click using the CUBA Studio (read-only demo version is available <a href="https://demo.cuba-platform.com/studio/">here</a>):</p>

![text]({{strapiUrl}}/uploads/7830747dbf2344bbb997fb06f66c7d94.png)

<p>CUBA offers convenient user interface for reports management:</p>

<ul style="margin-left: 40px;">
	<li>Report browser with options to import/export and run a report:</li>
</ul>

![text]({{strapiUrl}}/uploads/82164f8edbfb4e5483f08358f2270bfc.png)

<ul style="margin-left: 40px;">
	<li>The Report Editor allows you to create reports of any complexity (define bands, input parameters, manage templates, use Groovy, SQL, and JPQL to select the data):</li>
</ul>

![text]({{strapiUrl}}/uploads/233d0d0829aa421cb0f83e2d54ba80c0.png)

*   CUBA introduces [the report wizard](http://docs.cuba-platform.com/cuba/latest/reporting/en/html-single/reporting.html#wizard) functionality. With the help of the wizard, any user can rapidly create a report, even with limited knowledge of programming:

![text]({{strapiUrl}}/uploads/7cbfbb58185e402795b78f24ce16150a.png)

<h2>Conclusion</h2>

<p>To conclude the article let me skip usual boring deep thoughts (especially because all the information can be found <a href="http://docs.cuba-platform.com/cuba/latest/reporting/en/html-single/reporting.html">here</a>) and throw in a couple of my favourite reports:</p>

![text]({{strapiUrl}}/uploads/8ac8d0e1113e4d9cba9f4a165e8740d6.png)

![text]({{strapiUrl}}/uploads/0fdee88b93fd49a5a84f3ed18063bf01.png)

So, if you are interested follow the</span> <a href="https://github.com/cuba-platform/yarg" target="_blank">link</a> <span style="font-size: 15px;">and learn more! Note that YARG is completely free and available on</span> GitHub.
]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Platform at JavaOne 25-29 Oct]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-at-javaone</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-at-javaone</guid>
            <pubDate>Tue, 04 Aug 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/db021780907a4aeca94d8358a6f41929.png">We are happy to announce that CUBA Platform will be attending JavaOne - the world’s most prestigious Java event in the heart of Silicon Valley! You are most welcome to meet the CUBA team on our stand and discover more or share your ideas about the platform.]]></description>
            <content:encoded><![CDATA[<img style="float: left; margin-bottom:7px;margin-right:14px;" src="{{strapiUrl}}/uploads/a35697089a744f9daa6536d7f1edc142.png">

We are happy to announce that CUBA Platform will be attending JavaOne - the world’s most prestigious Java event in the heart of Silicon Valley! You are most welcome to meet the CUBA team on our stand and discover more or share your ideas about the platform.

If you are a fan of the learning-by-doing approach or just prefer to try things for yourself then join our Hands-on Labs on Wednesday, 28th at 10am, 12.30pm and 3pm. With the help of our CUBA experts, you will develop a fully-functioned business application in just a couple of hours. We’re also hosting a conference session ‘How to Develop Highly Customizable Off-the-Shelf Software' on 26th Monday at 4pm.

<span style="font-size:15px">If you would like to go and see us and other companies at the expo and haven’t arranged a ticket, we are giving away a limited number of free</span> <a href="https://www.oracle.com/javaone/register/compare.html" target="_blank">Discover Passes</a><span style="font-size:15px">. Simply register at</span> <a href="https://www.cuba-platform.com" target="_blank">www.cuba-platform.com</a> <span style="font-size:15px">and contact us to apply!</span>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Develop a Highly Customizable Product]]></title>
            <link>https://www.jmix.io/cuba-blog/how-to-develop-a-highly-customizable-product</link>
            <guid>https://www.jmix.io/cuba-blog/how-to-develop-a-highly-customizable-product</guid>
            <pubDate>Fri, 17 Jul 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/26dab3e0bc9040e79166536b6bc8aacd.jpg">How can the product be kept a step away from the potentially dangerous ideas of your customers, yet still satisfy them? How can it be possible to maintain the highest levels of performance for a product technically designed to function in a particular way, but now with a layer of numerous add-ins? How much of a challenge will be created by the fundamental need to provide unfailing and outstanding support to the developed solution?]]></description>
            <content:encoded><![CDATA[Have you ever heard: 'We really like your product…except for a few minor details.'? And then the CIO rolls out a list of additional 'must have' requirements, hundreds of them, to add to your amazing product. Have you ever heard, or even said: 'Team, we are about to sign up a highly-profitable contract but…'? And then the customer’s wish list for additional functionality becomes a headache for developers.

So, how can the product be kept a step away from the potentially dangerous ideas of your customers, yet still satisfy them? How can it be possible to maintain the highest levels of performance for a product technically designed to function in a particular way, but now with a layer of numerous add-ins? How much of a challenge will be created by the fundamental need to provide unfailing and outstanding support to the developed solution?

In the commercial world, product customization is an increasingly desirable requirement and a number of common practices have evolved in response to this customer need. Below you can find an overview of the typical approaches; if you are already familiar with them then you are welcome to scroll down straight to ‘**The Extensions Approach**’ paragraph and learn how we resolve these challenges in what we think is a more efficient way.

## All in One

The most straightforward and obvious solution to customization is to implement everything required in one core product and then employ the ‘feature toggle’ technique to match the requirements of each particular customer.  
The main advantage of the **All in One** approach is keeping the monolithic product, which appears to be a good way for certain types of products which generally cover business requirements without the need for extensive customization.

The natural limitation of this approach is hidden in the ‘not much customization required’ assumption. Often, a product development starts with this belief, but after a number of deliveries you realize the true scale of how much customer-specific functionality is required. It’s not uncommon to be caught on the horns of a dilemma; refuse custom development and potentially lose customers, or turn the source code into a **garbage can** with single-customer-specific features which are likely to be useless for the majority of end-users.

Which option would you choose? Obviously, choosing between a rock and a hard place is not the way to success.

_<u>Summary:</u> The All in One approach can be an appropriate choice only if you are sure that rare and limited customizations will be required. Otherwise, you’ll be faced by the choice between manageable and supportable product vs. customer satisfaction. Let me quote Jerry Garcia, who said: ‘Constantly choosing the lesser of two evils is still choosing evil’._

## Branching

If significant customization is the ‘must have’ part of a delivery then the **All in One** technique cannot be employed. There is another straightforward approach - **branching**. You simply branch the product codebase and change whatever in isolation.

Comparing **Branching** with **All in One**, the biggest advantage is that there are no limitations applicable to the scope of customization. You use separate branches to meet the specific requirements of different customers and avoid mixing all features in the same codebase.

However, there is a flip side of it that can become a dead end in terms of product evolution. Obviously, the product branch is the main development space: Most of the bugfixes, improvements, new functionality first get pushed to the product. Thus, frequent merging is required to keep all the customized branches synchronised with the core product. Merge is a simple operation as long as the original product source code has not been affected by the customized branch, otherwise it becomes extremely time consuming and can lead to unavoidable regression bugs.

This approach can still work if you are limited to a very few customized branches. However, as the number of delivered instances grows, the likelihood of facing the ‘torture by merge’ becomes imminent.

_<u>Summary:</u> The **Branching** approach is undoubtedly very flexible and straightforward – any part of a product can be modified. However, the post-delivery stage is potentially very laborious, becoming more difficult over time and it is very unlikely to result in delivering a significant number of manageable customized branches._

## The Entity-Attribute-Value Model

The <a href="https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model" target="_blank">Entity-Attribute-Value Model</a> (aka object–attribute–value model, vertical database model and open schema) is a well-known and widely-used data model. EAV enables dynamic entity attributes support and is typically used in parallel with the standard relational model.

From productization point of view the main advantage of using EAV is that you can deliver a product ‘as is’ and then adjust the data model by adding required attributes at runtime, keeping the source code clean.

As ever, there is a downside:

*   Limited applicability – The EAV model is limited by only enabling the addition of attributes to entities, which will then be auto-embedded to the UI, according to the pre-programmed logic.
*   Extra database server load - The vertical database design often becomes a bottleneck for enterprise applications, which generally operate with large numbers of entities and  attributes related to them.

Finally, enterprise systems cannot be imagined without the presence of a sophisticated reporting engine. The EAV model has the potential to bring in numerous complications because of its 'vertical' database structure.

_<u>Summary:</u> The **Entity-Attribute-Value** model has great value in certain situations, such as when there is a need to provide the flexibility achieved by having additional informative data, which is not explicitly used in business logic. In other words, EAV is good in moderation, e.g. in addition to the standard relational model and **plugin architecture**._

## The Plugin Architecture

The **Plugin** **architecture** is one of the most popular and powerful approaches – where functional logic is kept as separate artefacts known as plugins. To override existing out-of-the-box behaviour and run plugins, it is necessary to define the 'Points of Customization' (aka Extension Points) in the product source code. A 'Point of Customization' is a certain spot in source code where an application leafs through the attached plugins to check if a plugin contains overridden implementation to be run here. One of the variations of the plugin architecture is external scripting; when functional implementation is implemented and stored externally as a script. Script invocation is also controlled by predefined 'customization points'.

Using this plugin approach it is possible to keep the product 'clean' of specific customer requirements, deliver the core product ‘as is’ and customize the behaviour as required in plugins or scripts. Another advantage of this approach is a well managed update procedure. The full separation of product and plugin functionality enables each to be updated independently of each other.

Of course, limitations exist: The principal limitation is that it is impossible to have complete knowledge of which custom requirements could be raised in the future. Consequently, it is only possible to guess where 'points of customization' should be embedded. Of course, these could be scattered everywhere as a mitigating ‘Just in case’ plan, but this will lead to poor code readability, hard debug and additionally complicated support.

_<u>Summary:</u> The **Plugin architecture** does work if the 'customization points' are easy to predict, but be mindful that customization in between 'customization points' is impossible._

## The Extensions Approach

We have implemented a unique approach in our enterprise software development platform <a href="https://www.cuba-platform.com/" target="_blank">CUBA</a>. As articulated in our <a href="https://www.cuba-platform.com/blog/2015-06-29/416" target="_blank">previous article</a>, CUBA is very practical, living organism, created through a process of developer-driven evolution. So, based on our vast experience of off-the-shelf products, we came up with two ultimate requirements:

*   Customer-specific code should be fully separated from the core product code.
*   Every part of the product code should be available for modifications.

We managed to satisfy these requirements and achieve even more with our ‘Extensions’ mechanism.

### CUBA Extensions

An **extension** is a separate CUBA project which inherits all the features of an underlying project (i.e. your core product), using it as a library. This obviously enables developers to implement completely new functionality without affecting the parent project, but thanks to the use of the <a href="http://martinfowler.com/bliki/OpenInheritance.html" target="_blank">Open Inheritance</a> pattern and special CUBA facilities, you can also override any part of the parent project. In summary, an extension is the place where you implement the hundreds of ‘few minor details’ discussed at the beginning of this article.

In fact, every CUBA project is an extension of the CUBA platform itself - so it can override any platform feature. We adopted this approach ourselves to split out some out-of-the-box features (Full Text Search, Reporting, Charting, etc.) from the core platform. So if you need them in your project, you just add them as parent projects - that's it, kind of multiple inheritance!

In the same fashion, you can build a **hierarchical customization model**. This might sound complex, but it makes perfect sense. Let me give a real-world example: <a href="http://www.sherlocktaxi.com/" target="_blank">Sherlock</a> - is <a href="http://www.haulmont.com/" target="_blank">Haulmont’s</a> complete Taxi Management Solution, supporting every aspect of running a taxi business from booking and dispatch to apps and billing. The solution covers many different aspects of the client businesses and quite a few of them are location-related. E.g. all UK taxi companies have the same legal regulations, but many of them are not applicable for the United States, and vice versa. Obviously, we don’t want to implement all those regulations in the core product, because:

*   this is an ‘operation area specific’ feature
*   local regulations may have completely different effects for taxi fleet operations in different countries
*   some of the customers don’t require regulatory control at all

So, we organize the multilevel extensions hierarchy:

1.  Core product contains the generic features of taxi business
2.  The first level of customization implements regional specifics
3.  The second level of customization covers the customer’s wish list (if there is one!)

![text]({{strapiUrl}}/uploads/ad74950e66f64f739f152f7bbc4dc4c8.png)

Clean and clear.

As you see, by using extensions you neither need **branching** nor **integrating all requirements** in the core product, the code remains clean and manageable. It sounds too good to be true, so let's see how it works in practice!

### Adding a New Attribute to an Existing Entity

Let’s assume we have the product definition of User entity which consists of two fields: login and password:

    @Entity(name = "product$User")
    @Table(name = "PRODUCT_USER")
    public class User extends StandardEntity {
        @Column(name = "LOGIN")
        protected String login;

        @Column(name = "PASSWORD")
        protected String password;

        //getters and setters
    }

Now we have got an additional requirement from some of our customers to add the ‘home address’ field to users. To do that we extend the User entity in the extension:

    @Entity(name = "ext$User")
    @Extends(User.class)
    public class ExtUser extends User {

        @Column(name = "ADDRESS", length = 100)
        private String address;

        public String getAddress() {
            return address;
        }

        public void setAddress(String address) {
            this.address = address;
        }
    }

As you may have already noticed, all annotations, except for `@Extends` one, are common JPA annotations. The `@Extends` attribute is a part of the CUBA engine which globally substitutes the User entity to `ExtUser`, even across the product functionality.

Using the `@Extends` attribute we force the platform to:

1.  always create an entity of the ‘latest child’ type

        User user = metadata.create(User.class); //ExtUser entity will be created

2.  transform all the JPQL queries before the execution so that they always return the ‘latest childset’

        select u from product$User u where u.name = :name //returns a list of ExtUsers

3.  always use the ‘latest child’ in the associated entities

        userSession.getUser(); //returns an instance of ExtUser type

In other words, if an extended entity is declared, the base one is abandoned across the entire solution (product and extension) and is globally overridden by the extended one.

### Screens Customization

<p>So, we have extended the User entity by adding the address attribute and now want the changes to be reflected in the user interface. First, let us have a look on the original (product) screen declaration:</p>

```java
<window
        datasource="userDs"
        caption="msg://caption"
        class="com.haulmont.cuba.gui.app.security.user.edit.UserEditor"
        messagesPack="com.haulmont.cuba.gui.app.security.user.edit">

    <dsContext>
        <datasource
                id="userDs"
                class="com.haulmont.cuba.security.entity.User"
                view="user.edit">
           </datasource>
    </dsContext>

    <layout>
        <fieldGroup id="fieldGroup" datasource="userDs">
            <column>
                <field id="login"/>
                <field id="password"/>
            </column>
        </fieldGroup>
      
        <iframe id="windowActions" screen="editWindowActions"/>
    </layout>
</window>
```

<p>As you can see, a CUBA screen descriptor is represented as an ordinary XML. Obviously, we could simply re-declare the entire screen descriptor in the extension, but this would mean copy-pasting most of it. In result, if something changes in the product screen in the future, we will have to copy these changes to the extension screen manually. To avoid this, CUBA introduces the screen inheritance mechanism and all you need is describe changes to the screen:</p>

```java
<window extends="/com/haulmont/cuba/gui/app/security/user/edit/user-edit.xml">
    <layout>
        <fieldGroup id="fieldGroup">
            <column>
                <field id="address"/>
            </column>
        </fieldGroup>
    </layout>
</window>
```

<p>You define the ancestor screen using the extends attribute and only describe the subject to change.</p>

<p>Here you are! Let’s finally have a look at the result:</p>

![text]({{strapiUrl}}/uploads/b171a31f0e7b4c20910bbcd3cbfe05c8.png)

<h3>Modification of the Business Logic</h3>

<p>To enable business logic modification the CUBA platform uses Spring Framework, which forms a core part of the platform infrastructure.</p>

<p>For example, you have a middleware component to perform price calculation procedure:</p>

```java
@ManagedBean("product_PriceCalculator")
public class PriceCalculator {
    public void BigDecimal calculatePrice() { 
        //price calculation
    }
}
```

<p>To override the price calculation implementation we only need to undertake two simple actions.</p>

<p>First, extend the product class and override the corresponding procedure:</p>

```java
public class ExtPriceCalculator extends PriceCalcuator {
    @Override
    public void BigDecimal calculatePrice() { 
               //modified logic goes here
    }
}
```

<p>And as a final touch, register the new class in the Spring configuration using the product bean identifier:</p>

```java
 <bean id="product_PriceCalculator" class="com.sample.extension.core.ExtPriceCalculator"/>
```

<p>Now <em>PriceCalculator</em> injection will always return the extended class instance. Consequently, the modified implementation will be used across the whole product.</p>

<h3>Upgrading Base Product Version in Extension</h3>

<p>As the core product evolves and new versions are released you will eventually decide to upgrade your extension to the latest product version. The process is quite simple:</p>

<ol style="margin-left: 40px;">
	<li>Specify the new version of the underlying product in extension.</li>
	<li>Rebuild the extension:</li>
</ol>

<ul style="margin-left: 80px;">
	<li>If an extension is built over the stable parts of the product API, then it is ready to run.</li>
	<li>If some significant modifications of the product API have taken place and those modifications overlap customization implemented in the extension, it will be necessary to support the new product API in the extension.</li>
</ul>

<p>Most of the time a product API does not change significantly from update to update, especially in minor releases. But even if an API ‘big-bang’ occurs, a product usually keeps downward compatibility for at least a couple of future versions and the old implementation is marked as ‘deprecated’, allowing all extensions to be migrated to the newest API.</p>

<h2>Conclusion</h2>

<p>As a short summary I would like to illustrate the result of the comparative analysis in a tabular form:</p>

![text]({{strapiUrl}}/uploads/240cd5d8ff72437ea86a679a625144f0.PNG)

<p>As you can see the Extension approach is powerful, but one thing it lacks is the ability to fine-tune the system on the fly (dynamically customized). To overcome this, CUBA also provides full support for the <strong>Entity-Attribute-Value</strong> model and <strong>Plugin/Scripting</strong> approach.</p>

<p>I hope you will find this overview useful and of course your feedback is much appreciated.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Philosophy of the CUBA Platform]]></title>
            <link>https://www.jmix.io/cuba-blog/the-philosophy-of-the-cuba-platform</link>
            <guid>https://www.jmix.io/cuba-blog/the-philosophy-of-the-cuba-platform</guid>
            <pubDate>Mon, 29 Jun 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/7a6c0f3e823340248b76792b599ffee0.png">A huge amount has happened recently. Following the official launch of CUBA on 1st of June, we have rolled out a new release, published our first article on a few Java sites and presented the platform at the Devoxx UK сonference in London. But before the rush continues, about it is an apt time to articulate the philosophy behind CUBA.]]></description>
            <content:encoded><![CDATA[A huge amount has happened recently. Following the official launch of CUBA on 1st of June, we have rolled out a new release, published our first article on a few Java sites and <a href="https://www.cuba-platform.com/blog/2015-06-25/411" target="_blank">presented the platform at the Devoxx UK сonference in London</a>. But before the rush continues, about it is an apt time to articulate the philosophy behind CUBA.

The first words associated with enterprise software development will probably be: slow, routine, complex and convoluted - nothing exciting at all! A common approach to combat these challenges is raising the level of abstraction - so that developers can operate with interfaces and tools encapsulating internal mechanisms. This enables the focus on high-level business requirements without the need to reinvent common processes for every project. Such a concept is typically implemented in frameworks, or platforms.

The <a href="https://www.cuba-platform.com/blog/2015-06-01/389" target="_blank">previous CUBA article</a> explained why CUBA is more than just a bunch of well-known open-source frameworks comprehensively integrated together. In brief, it brings declarative UI with data aware visual components, out-of-the-box features starting from sophisticated security model to BPM, and awesome development tools to complement your chosen IDE.

You can easily find more details on our <a href="https://www.cuba-platform.com/tutorials">Learn page</a>, so instead of listing all of them I'll try to "raise the abstraction level" and explain the fundamental principles of CUBA.

## Practical

The platform is a living organism, and its evolution is mostly driven by specific requests from developers. Of course, we constantly keep track of emerging technologies, but we are rather conservative and employ them only when we see that they can bring tangible value to the enterprise software development. As a result, CUBA is extremely practical; every part of it has been created to solve some real problem.

## Integral

Apart from the obvious material features, the visual development environment provided by CUBA Studio greatly reduces the learning curve for newcomers and juniors. It is even more important that the platform brings a unified structure to your applications. When you open a CUBA-based project, you will always know where to find a screen, or a component inside of it; where the business logic is located and how is it invoked.

Such an ability to quickly understand and change the code written by other developers cannot be underestimated as a significant benefit to continual enterprise development. An enterprise application lifecycle may last tens of years and your solution must constantly evolve with the business environment, regardless of any changes in your team. For this reason, the flexibility to rotate, or scale up or down the team when needed, is one of the major concerns for the companies, especially those who outsource development or have distributed teams.

## Open

One of the key principles of CUBA is openness. This starts with the full platform source code, which you have at hand when you work on a CUBA-based project. In addition, the platform is also open in the sense that you can change almost any part of it to suit your needs. You don't need to fork it to customize some parts of the platform - it is possible to extend and modify the platform functionality right in your project. To achieve this, we usually follow the open inheritance pattern, providing access to the platform internals. We understand that this can cause issues when the project is upgraded to a newer platform version. However, from our experience, this is far less evil than maintaining a fork, or accepting the inability to adapt the tool for a particular task.

We could also make a number of specific extension points, but in such case we would have to anticipate how application developers will use the platform. Such predictions always fail, sooner or later. So instead we have made the whole platform extension-friendly: you can inherit and override platform Java code including the object model, XML screens layout and configuration parameters. Transitively, this remains true for CUBA-based projects. If you follow a few simple conventions, your application becomes open for extension, allowing you to adapt the single product for many customers.

## Symbiotic

CUBA is not positioned as a “thing-in-itself”. When a suitable and well-supported instrument already exists and we can integrate with it without sacrificing platform usability, we will integrate with it. An illustration of such integrations is full-text search and BPM engines, JavaScript charts and Google Maps API. At the same time, we have had to implement our own <a href="https://www.cuba-platform.com/YARG" target="_blank">report generato</a> from scratch, because we could not find a suitable tool (technology and license wise).

The CUBA Studio follows this principle too. It is a standalone web application and it doesn't replace your preferred IDE. You can use Studio and the IDE in parallel, switching between them to accomplish different tasks. WYSIWYG approach, implemented in Studio, is great for designing the data model and screens layout, while the classic Java IDE is the best for writing code. You can change any part of your project right in the IDE, even things created by Studio. When you return to Studio, it will instantly parse all changes, allowing you to keep on developing visually. As you see, instead of competing with the power of Java IDEs, we follow a symbiotic approach. Moreover, to raise coding efficiency, we’ve developed plugins for the most popular IDEs.

When we integrate with a third-party framework, we always wrap it in a higher level API. This enables replacing the underlying implementation if needed and makes the whole platform API more stable long term and less dependent on the constant changes in the integrated third-party frameworks. However, &nbsp;we don't restrict the direct use of underlying frameworks and libraries. It makes sense if CUBA API does not fit a particular use case. For example, if you can't do something via Generic UI, you can unwrap a visual component and get direct access to Vaadin (or Swing). The same applies for data access; if some operation is slow or not supported by ORM, just write SQL and run it via JDBC or MyBatis. Of course, such “hacks” lead to more complex and less portable application code, but they are typically very rare compared to the use of standard platform API. This knowledge of inherent flexibility and a sense of &nbsp;“Yes you can” adds a lot of confidence to developers.

## Wide Use Area

We recommend using CUBA if you need to create an application with anything starting from 5-10 screens, as long as they consist of standard components like fields, forms, and tables. The effect from using CUBA grows exponentially with the complexity of your application, independent of the domain. We have delivered complex projects in financial, manufacturing, logistics and other areas. As an example, a non-obvious, but popular use case is using CUBA as the backend and admin UI, while creating the end-user interface with another, lighter or more customizable web technology.
 
I hope you will see some use cases of the platform for yourself, so in the next articles we’ll focus on “what's under the hood” – as we provide a&nbsp;detailed overview of the different CUBA parts.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Platform was Introduced to the Public]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-was-introduced-to-the-public-at-devoxx-uk</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-was-introduced-to-the-public-at-devoxx-uk</guid>
            <pubDate>Thu, 25 Jun 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/0c4eeb91c9524cd19487bfe77b02ac91.PNG">CUBA Platform was introduced to the public at Devoxx UK 2015: we met many of the 1000 participants, held over 50 comprehensive discussions, got some great feedback, had pleasant meeting with colleagues from Vaadin… All that has lead to a range of new fruitful ideas - thanks to Devoxx!]]></description>
            <content:encoded><![CDATA[CUBA Platform was introduced to the public at Devoxx UK 2015: we met many of the 1000 participants, held over 50 comprehensive discussions, got some great feedback, had pleasant meeting with colleagues from Vaadin… All that has lead to a range of new fruitful ideas - thanks to Devoxx!


![text]({{strapiUrl}}/uploads/96e11fe69a3540cca7b953a1fc6718e7.PNG)

![text]({{strapiUrl}}/uploads/acc2c7d8e259405e9270b41c9b4ba72a.PNG)

CUBA team presented a speech illuminating the hidden side of building a new framework and explaining the choice of key technologies and the philosophy of the CUBA platform.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's New in CUBA Platform 5.5 and Studio 1.5]]></title>
            <link>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-5-5-and-studio-1-5</link>
            <guid>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-5-5-and-studio-1-5</guid>
            <pubDate>Wed, 17 Jun 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/54eed901823746f5bcd7a55f035c9c17.png">The new version of CUBA platform has been released! We bring more and more improvements and features, all aimed to make the development process more efficient.

So, what's new in CUBA platform 5.5 besides of bugfixes and how CUBA can make your life easier.]]></description>
            <content:encoded><![CDATA[The new version of CUBA platform has been released! We bring more and more improvements and features, all aimed to make the development process more efficient.

So, what's new in CUBA platform 5.5 besides of bugfixes and how CUBA can make your life easier.

## Main Window Layout

CUBA applications often look similar because of the standard main window layout: the main menu is on top, the folders panel on the left, the user indicator on the top right corner... Previously, to change this layout, you had to extend <span style="font-family:courier new,courier,monospace">App</span> and <span style="font-family:courier new,courier,monospace">AppWindow</span>, override a number of methods and use Vaadin components directly - a high price to pay for your exclusive interface.

Now you can create the main window as any other application screen using the Generic UI technology. The main window can contain any CUBA visual components and use  datasources to work with the data model. There are also a few specific main window components, such as <span style="font-family:courier new,courier,monospace">AppMenu</span>, <span style="font-family:courier new,courier,monospace">AppWorkArea</span>, <span style="font-family:courier new,courier,monospace">UserIndicator</span>, etc. The main window has the special <span style="font-family:courier new,courier,monospace">mainWindow</span> identifier, which is used to load it and to differentiate it from the other screens of your application.

Using CUBA Studio you can extend the standard main window or create a completely new one from scratch. The _Create main window_ link in the _Screens_ section opens the WYSIWYG designer with the components palette, which contains the special main window components in addition to the standard ones:

![text]({{strapiUrl}}/uploads/11f14c22707247779a1c96ac658b6ce7.png)

Apparently the most demanded customization of the main window is to show something on the working area when no screens are opened. It could be a welcome message, shortcuts to the most used screens or a dashboard with data or charts.

To implement a new “initial layout”, click _Create main window_, find the <span style="font-family:courier new,courier,monospace">initialLayout</span> element inside <span style="font-family:courier new,courier,monospace">workArea</span> and add your components to it:

![text]({{strapiUrl}}/uploads/72073fd4af52438888f63db8508da5bd.png)

After that you can add a datasource, link it to your new table or a chart, and load the datasource in your Java controller. Below you can see an example of what you can get using the new feature of customizing the main window layout:

![text]({{strapiUrl}}/uploads/59c1337cac31480aafae91232467cc11.png)

So, when users open another application screen, it will be brought above the initial layout.

You can also completely redesign your main window and without using any special components, including WorkArea. To do this, click _Create main window_ (or _Edit main window_ if you have already created one), clear the _Descriptor extends_ field and select *AbstractMainWindow</span> in the _*Controller extends*_ field. After that, create the components structure:

![text]({{strapiUrl}}/uploads/1406681e962a4c0488983118620b795d.png)

So your application may look like this:

![text]({{strapiUrl}}/uploads/ebe613dfb7d74404b9a87d2a9003405b.png)

The logout button is in the bottom-left corner, a control button is in the top left corner. If you don’t provide the WorkArea, you will be able to open screens in dialog windows only. The following code shows how to open a screen without the main menu:

```java
public void openUsers() {
    getDialogParams().setResizable(true).setWidth(800).setHeight(600);
    openWindow("sec$User.browse", WindowManager.OpenType.DIALOG);
}
```

The following code shows how to log out:

```java
public void logout() {
    WebWindowManager wm = (WebWindowManager) getWindowManager();
    wm.closeAllWindows();
    wm.getApp().getConnection().logout();
}
```

There is one limitation: the GUI-level main window works only in the web client.

## Dynamic Attributes

CUBA dynamic attributes are aimed to extend data model at runtime without restarting and rebuilding your application. System administrators or even end users can create new attributes at deployment stage or in production environment.

Previously, this functionality was limited:

*   dynamic attributes could be added only for an entity extending a special base class
*   dynamic attributes could be displayed only through a special component - <span style="font-family:courier new,courier,monospace">RuntimePropertiesFrame</span>

In the new platform version these restrictions are eliminated: a user can add dynamic attributes to any entity and set up their display in <span style="font-family:courier new,courier,monospace">FieldGroup</span> and <span style="font-family:courier new,courier,monospace">Table</span> components already presented on the screen.

Initially, a new dynamic attribute is not displayed on any screen. You should open the _Visibility_ tab of the _Attribute editor_ and explicitly add target screens:

![text]({{strapiUrl}}/uploads/d2587838282c422e8985e226c658b1a9.png)

_Component ID_ is optional: if it is not specified, the attribute will be displayed on all <span style="font-family:courier new,courier,monospace">FieldGroup</span> and <span style="font-family:courier new,courier,monospace">Table</span> components connected to the appropriate datasource. Apparently, in most cases, a screen contains only one such component.

Don’t forget to click _Apply changes_ in the _Categories_ screen, otherwise your changes will have no effect.

A system administrator can restrict access to dynamic attributes for users. This option is available through the standard _Role_ edit screen. Dynamic attributes are represented by their codes with the “+” prefix.

Dynamic attributes are now accessible through the REST API if you provide the <span style="font-family:courier new,courier,monospace">dynamicAttributes=true</span> parameter for <span style="font-family:courier new,courier,monospace">find</span> or <span style="font-family:courier new,courier,monospace">query</span> request. All attributes passed to <span style="font-family:courier new,courier,monospace">commit</span> will be saved.

Besides working with dynamic attributes in the UI or through the REST API, you can access them in the application code. It is needed if you incorporated some dynamic attributes into the system at design time. For example, let’s create the Phone dynamic attribute for the Customer entity. Don’t add any target screens - we will set up attribute display in the source code.

In order to display the attribute on the browser screen, add the <span style="font-family:courier new,courier,monospace">loadDynamicAttributes</span> XML attribute to the datasource definition:

```java
<collectionDatasource id="customersDs"
                    class="com.company.sample.entity.Customer"
                    view="_local"
                    loadDynamicAttributes="true">
  <query>
      <![CDATA[select e from sample$Customer e]]]]><![CDATA[>
  </query>
</collectionDatasource>
```

Then add a table column referring the attribute by code with the “+” prefix:

```java
<table id="customersTable">
  <columns>
      <column id="name"/>
      <column id="email"/>
      <column id="+phone" caption="Phone"/>
  </columns>
```

The same should be done for the edit screen, with the difference that the <span style="font-family:courier new,courier,monospace">FieldGroup</span> <span style="font-family:courier new,courier,monospace">field</span> should be added instead of <span style="font-family:courier new,courier,monospace">column</span>. Moreover, you can use any appropriate visual component to edit the attribute value:

```java
<maskedField datasource="customerDs" property="+phone"
           mask="### ### ###" caption="Phone" />
```

Although dynamic attributes can be very attractive, you should use them with caution. Keep in mind - all the attribute values are stored in a single table, and loading entities with dynamic attributes requires at least one additional select from this table. This may affect performance of your system. Also, dynamic attributes can complicate difficulties for report creation, in contradistinction to plain entities stored in separate tables which are easy to use in reporting.

## Performance Statistics

The _Performance Statistics_ screen enables you to watch and trace some performance-related runtime parameters of your application: request and transaction rates, parameters of the database pool, memory and CPU usage. The screen shows three value for each parameter:

*   current (last measured) value
*   average value for the time while the screen is open
*   average value for the entire server uptime.

Thus you can quickly compare the current value, recent average and long-term average, which can help to find out a cause of possible performance issues:

![text]({{strapiUrl}}/uploads/ea6b9e179aa74d57adfa1aa8537697b8.png)

Notice that current and long-term average values are also available through the <span style="font-family:courier new,courier,monospace">app-core.cuba:type=StatisticsCounter</span> JMX bean and thus can be retrieved by any third-party JMX tool.

The _Threads_ button opens another screen which shows the list of threads. You can sort threads by _CPU usage_ column and examine the invocation stack of the selected thread:

![text]({{strapiUrl}}/uploads/579a5c384faf4bc09c94c489aad932ee.png)

## CUBA Studio 1.5

With the new Studio release you get more flexibility and convenience of CUBA applications development.

Now you can download sample projects from GitHub right through Studio interface - the projects show the best practices of the platform use and help to reduce “barriers to entry”. Click _Samples_ button in the _Select project_ window, and the list of samples will be fetched from GitHub. Select a sample, choose a local path for the project, and click OK:

![text]({{strapiUrl}}/uploads/2bd890957ec246ac8d6dc33b662c4788.png)

The selected project will be downloaded and imported into Studio, so you will see it in the _Select project_ window:

![text]({{strapiUrl}}/uploads/6a988670d32a454a9b7816d540c29f9e.png)

The list of samples is short now, but we plan to significantly extend it. We will publish simple learning examples, as well as full-fledged applications which can be useful in real life.

The _Show changes_ button enables you to review modifications before saving them. It is available on all designer pages, as well as in the confirmation dialog which appears while closing a page containing unsaved changes:

![text]({{strapiUrl}}/uploads/fc1ab8a1c20c4c28a9145a80863a4c45.png)

<span style="font-size:15px">Additional project dependencies can be specified on the</span> _Advanced_ <span style="font-size:15px">tab of the project properties page. Here you can also change the artifacts prefix and web application names - explore the</span> _Modules prefix_ <span style="font-size:15px">field.</span>

![text]({{strapiUrl}}/uploads/d9c9c619fc0b48858251880294b698e6.png)

<span style="font-size:15px">HSQL database files are now located inside the project folder in</span> <span style="font-family:courier new,courier,monospace; font-size:15px">build/hsqldb</span> <span style="font-size:15px">subdirectory. Previously, those have been stored in the Studio home directory, what could cause problems for prototyping projects with the same database names. The new Studio automatically copies old databases to the project folder while the project is being opened.</span>

The entity designer became smarter in handling attribute type and nullability changes.

Now you have greater arsenal of tools to teach Studio not to make undesirable modifications to your database scheme. First, you can exclude generated database update scripts from the execution list. Unlike removed scripts, excluded scripts are remembered for the project and are not generated again. Second, you can specify a prefix for database columns that should not be tracked by Studio on the _Settings_ page.

The detailed release notes of CUBA Platform 5.5 are available <a href="http://files.cuba-platform.com/cuba/platform/platform-5.5-changelog.html" target="_blank">here</a>.
The full list of changes in this Studio release can be found <a href="http://files.cuba-platform.com/cuba/studio/studio-1.5-changelog.html" target="_blank">here</a>.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CUBA Platform at Devoxx UK]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-at-devoxx-uk</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-at-devoxx-uk</guid>
            <pubDate>Tue, 02 Jun 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/9995b8103210474091e205b74e8665b7.jpg">We are excited to announce that CUBA Platform is the Silver sponsor of the <a href="http://www.devoxx.co.uk" target="_blank">Devoxx</a> UK Java conference, which will be held in London at the Business Design Centre, 17th-19th June.]]></description>
            <content:encoded><![CDATA[We are excited to announce that CUBA Platform is the Silver sponsor of the <a href="http://www.devoxx.co.uk" target="_blank">Devoxx</a> UK Java conference, which will be held in London at the Business Design Centre, 17th-19th June. Please come and see us at stand S5 or visit our session called The Dark Arts of Building Your Own Framework on Thursday at 14:40.]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The New Java Enterprise Applications Framework]]></title>
            <link>https://www.jmix.io/cuba-blog/cuba-platform-the-new-java-enterprise-applications-framework</link>
            <guid>https://www.jmix.io/cuba-blog/cuba-platform-the-new-java-enterprise-applications-framework</guid>
            <pubDate>Mon, 01 Jun 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/bfcaf34830714136a579da7198a2ee92.jpg">Update: CUBA Platform made impressive progress since when this article was published. To get the most up-to-date information, I recommend reading it's new version, published recently in our blog.]]></description>
            <content:encoded><![CDATA[<span style="font-size:18px">Update: CUBA Platform made an impressive progress since when this article was published. To get the most up-to-date information, I recommend reading it's <a href="http://www.cuba-platform.com/blog/open-source-java-rad-framework" target="_blank">new version</a>, published recently in our blog.</span>

So... hello world! Our English website is finally live and now everyone can download the platform and start creating business applications faster than ever before, honestly. It took us six years of permanent evolution and occasional revolutions to get CUBA to the level of maturity before we decided it is good enough to share with the international Java community, including a couple of years to create extensive documentation, video tutorials and live applications with code samples. Since 2009 the framework has been battle-proven in numerous projects by Haulmont and other IT companies, ranging from a simple website backend to end-to-end enterprise automation solutions running 24x7 or serving thousands of concurrent users.

As mentioned above, CUBA is aimed at business applications. We assume that such applications will often require complex data models, hundreds of screens, support for running various business processes, strong security requirements and mult<span style="font-size:15px">iple integrations. Alongside all this, they should be scalable and ready for permanent changes as the business evolves.</span>

So what is CUBA and how is it different from tools and frameworks already available out there? In short, it is a full stack Java framework based on a number of technologies: Spring, Vaadin, EclipseLink, Lucene, Activiti, Gradle, etc. However, using these (or similar) technologies separately still requires too much effort to develop complex applications, so CUBA introduces tight integration between them.

CUBA applications have a standard three-tier architecture. The nexus is metadata - the knowledge of the application data model. First, it makes all visual components data-aware. So for instance a table ‘knows’ it is displaying certain attributes of a driver entity, and a label ‘knows’ that it is displaying a date. Similarly, metadata helps visual components to talk to the ORM - defining the graph of objects which should be loaded or updated. The same applies to the security subsystem, report generator and other parts of the platform.

The UI is declarative: you define screens layout in XML or in a visual editor choosing from 70+ visual components ranging from all sorts of buttons to Google Maps and dynamic charts. Then you add the initialization and event handling logic in Java controllers. Considering data-aware components, you can create a sophisticated UI very quickly and it will remain easy to maintain thanks to clear separation between code and layout. A rich web client is used by default - which obviously means you do not need to worry about installing anything to end user PCs. In addition, the same UI can be displayed in a desktop Java client, and you can even use both simultaneously in your application.

![text]({{strapiUrl}}/uploads/822af541dc02446397abdcd086d8701e.png)

An important part of the UI is the Generic Filter - a component which allows users to create their own search conditions. A developer just needs to drop the component to a browser screen (a screen showing a list of entities) and forget about it. Users or administrators will define conditions they want to search on themselves.

![text]({{strapiUrl}}/uploads/bc7810e45f264d799edc483c6f65059d.png)

All user actions are controlled by the security subsystem. The role based model controls CRUD access down to entity attributes, and even certain screen components or custom tokens which you can use in your code. Row level security helps to control access to different pieces of data - for example users from Department A will only see documents from Department A. Of course, everything is configured at runtime in UI. Finally, all changes to the data are logged, so you will see who changed what and when, with the ability to revert - handy for debriefing when something went wrong.

In addition to the above, CUBA provides many features out of the box, including:

*   Business process management with an integrated visual designer
*   Reports generation
*   Full text search
*   Universal REST API to integrate with external systems
*   Credit card payments support
*   Reliable asynchronous email sending
*   Scheduled tasks execution support
*   Soft deletion

… and many more, covering most of the needs of a typical enterprise application.

When it comes to deployment and environment options, you have a lot of freedom here. CUBA applications can be deployed in a variety of configurations, starting from a single server running everything, to highly available configurations with separate middleware and web clusters. CUBA supports PostgreSQL, Oracle Database, Microsoft SQL Server and HSQL (typically used for prototyping) out of the box, and you can switch from one to another as your project grows. If you want to use another DBMS - not a problem, you can add support for it with a little effort. It is also important that CUBA applications can be deployed to any Java EE Web Profile server, such as Tomcat, Glassfish, etc.

Finally, a few words about how you actually develop applications on CUBA. All you need is Java SE, XML and JPQL - which makes your application code more uniform and easier to maintain. This also reduces requirements to your development team - you don’t really need a subteam of Web developers or Java EE gurus.

![text]({{strapiUrl}}/uploads/45ff7e5478c7497f87b67d0ade281fb7.png)

You create your business logic in a standard IDE like IntelliJ IDEA or Eclipse, but CUBA also features Studio - a supplementary tool which enables visual screens layout design, helps to create a data model and generate standard screens for it, generates, runs, and keeps up-to-date DB update scripts, creates and configures your project and build files and automates a variety of other routine work (which few people enjoy doing manually). All changes between Studio and the IDE are synchronized, so you have a choice of where to make them.

And to boost developer performance even further, CUBA supports hot deploy for all your code except the data model. So for instance, if you changed a screen or a method, you don’t need to restart the server anymore. Imagine how many hours you spend waiting for the stop-compile-deploy-start process (though this has been a good excuse for one more cup of coffee!). With CUBA, you just reopen the screen or invoke the method again and you will see your changes. Hot deploy can be invoked by a Gradle task, but it is easier to let CUBA Studio do it automatically in background as soon as it detects any changes.

There is still a lot of things I’m tempted to talk about, but hopefully this gives enough flavour to give CUBA a try. And in case something does not work - don’t hesitate to ask for help via our support forum!]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What's New in CUBA Platform 5.4 and Studio 1.4]]></title>
            <link>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-5-4-and-studio-1-4</link>
            <guid>https://www.jmix.io/cuba-blog/whats-new-in-cuba-platform-5-4-and-studio-1-4</guid>
            <pubDate>Wed, 22 Apr 2015 00:00:00 GMT</pubDate>
            <description><![CDATA[<img src="https://www.jmix.io/uploads/45fe0373316f4a4293ac8fe65d0e972f.png">CUBA Platform 5.4 has now been released, bringing new features, as well as a number of bug fixes and improvements. This is also the first release available on the English version of our website.

As usual, we have released a new version of Studio, supporting projects based on the Platform 5.4. Besides the automatic migration to the new platform version, this Studio release offers some useful new features]]></description>
            <content:encoded><![CDATA[CUBA Platform 5.4 has now been released, bringing new features, as well as a number of bug fixes and improvements. This is also the first release available on the English version of our website. The detailed release notes are available <a href="http://files.cuba-platform.com/cuba/platform/platform-5.4-changelog.html" target="_blank">here</a>.

## Filter

Perhaps the most notable new feature is the redesigned Filter component. Now it looks more clear and compact: only the widely used functions are available, others are hidden inside the drop-down lists.

Here is how an empty filter looks:

![text]({{strapiUrl}}/uploads/ddbafb8c9647447681ccbfafa1df4bf6.png)

The updated component supports ad-hoc filtering: to use a filter, you don't need to "create" and save it first. You can immediately add conditions, select comparison operations, enter search criteria and then apply the filter. The following image shows a filter with three conditions:

![text]({{strapiUrl}}/uploads/c71bd4b891c24a6eb6cb08e62c91e71c.png)

Note the blue cross signs - now you can instantly remove the conditions. The asterisk in the filter caption means that the filter is changed and should be saved if required for later use.

Selection of a pre-saved filter:

![text]({{strapiUrl}}/uploads/9d299c1478ff472ea426456f625f1be0.png)

A saved filter can be modified in a separate modal window opened by the Edit command available in the Settings popup button.

The layout of Filter in your project can be easily customized by means of the cuba.gui.genericFilterControlsLayout application property. For example, if you set it to the value

```java
cuba.gui.genericFilterControlsLayout = [add_condition] [spacer] \ 
    [filters_popup] [save | no-caption] \ 
    [settings | save_as, edit, remove, make_default, pin, \ 
        save_search_folder, save_app_folder] \ 
    [max_results] [fts_switch]
```

the filter will look as below:

![text]({{strapiUrl}}/uploads/cb67c1bec1d543daa9ab03000fdf50e4.png)

As you can see, the “Add search condition” link goes first, and the “Save” command has been pulled from the “Settings” popup and placed onto the main panel as a button without caption.

A pre-saved filter in this layout:

![text]({{strapiUrl}}/uploads/90c1098687894d79a13e7fc74f5906aa.png)

To allow even deeper customization, we encapsulated most of the filter functionality in the FilterDelegateImpl managed bean, which can be extended in your project.

You can get much more from the filter if you use the Full-Text Search base project. If the filter is connected to a datasource with an indexed entity, it will show the additional “Full-Text Search” checkbox:

![text]({{strapiUrl}}/uploads/bf9b76d359c54a32b39ae6389a596029.png)

In the FTS mode, the filter contains only one input field and the “Search” button:

![text]({{strapiUrl}}/uploads/f7901f48d7c64950ae246bdc6b86b5ad.png)

When you enter a search term, the filter looks up appropriate entities in the full-text index, and then loads the matching instances from the database taking into account security constraints.

## Time Zones

Another enhancement is user time zones support. A time zone is assigned to a user by system administrator in the user editor screen; alternatively the user can choose it himself in the Help > Settings screen. A time zone can be either defined explicitly, or set to “Auto” value. In the latter case the user time zone will be acquired from the web browser or desktop client OS, which is convenient for travelling users. If set, the timezone is shown in the main window next to the login name.

The user time zone affects DateTime attributes displayed in the Table and DateField components. The application code always works with time in the server time zone. The components convert time values from server time to a user time for display, and from the user time to server time when the user enters new values. If you don’t need such conversion for a particular attribute, annotate it with @IgnoreUserTimeZone.

## The DataManager Interface

The new DataManager interface is intended for uniform access to data both from the middle and client tiers. It works with detached entities and always starts new transactions when it loads and commits entities.

So now the platform provides two interfaces to work with entities: EntityManager and DataManager. Below is a list of distinctions between them.

<table>

<tbody>

<tr>

<td>EntityManager mostly resembles the standard javax.persistence.EntityManager.</td>

<td>DataManager defines a few high-level methods for working with detached entities: load(), loadList(), reload(), commit().</td>

</tr>

<tr>

<td>EntityManager is available only on the middle tier.</td>

<td>DataManager is available on both middle and client tiers.</td>

</tr>

<tr>

<td>You should obtain a reference to EntityManager through the Persistence interface.</td>

<td>

DataManager is a singleton bean.

</td>

</tr>

<tr>

<td>

You have to open a transaction before working with EntityManager.

</td>

<td>DataManager starts new transactions internally.</td>

</tr>

<tr>

<td>EntityManager does not impose security constraints.</td>

<td>DataManager applies all security constraints except entity attribute permissions.</td>

</tr>

</tbody>

</table>

## REST API

You can now call arbitrary services through the standard REST API. Service methods can have parameters and results of primitive types or corresponding object wrappers, entities and collections of entities.

For security reasons, a service should be registered in the special configuration file before it will become available through the REST API.

## CUBA Studio 1.4

As usual, we have released a new version of Studio, supporting projects based on the Platform 5.4\. Besides the automatic migration to the new platform version, this Studio release offers some useful new features:

*   Full Entity Listeners support.
*   Hot deploy now works for views.xml, screens.xml and menu.xml. It means that if your project is based on the platform version 5.4+, you don’t need to restart the application server when you change views, modify and register new screens and main menu items.
*   Full support for transient attributes in persistent entities.
*   When you create a Many-To-Many association, it becomes owning on the both sides. So the newly generated standard screens for both sides of the association will have Add/Edit/Remove controls.
*   We have added a toolbar with some frequently used actions.
*   The project search, invoked by the “Alt+/” shortcut, now includes more actions which enables working with Studio with the keyboard only.

The full list of changes in this Studio release can be found <a href="http://files.cuba-platform.com/cuba/studio/studio-1.4-changelog.html">here</a>.]]></content:encoded>
        </item>
    </channel>
</rss>