All articles
Contents

    CUBA 7.2 - what's new?

    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

    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

    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

    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

    The full list of updates can be found here, 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 here.

    Jmix is an open-source platform for building enterprise applications in Java