Platform
All Resolved Issue
-
Platform 6.7.8 Resolved Issues
WarningKnown issue:
If a new project with BPM module is created based on platform v 6.7.8, then during the database script generation Studio will create the database update script modifying the BPM_PROC_INSTANCE entity. The script will remove 3 colums: STRING_ENTITY_ID, INT_ENTITY_ID, LONG_ENTITY_ID. You can safely apply this script.
Breaking Changes
-
The authentication mechanism has been refactored to be more extensible. The
LoginServiceBean
andLoginWorkerBean
classes are now deprecated and just delegate to the new mechanism. If you have overridden them in your project, you need to migrate your extension to using the new functionality. For example, you can use events to intercept login on the middle tier. -
Due to improvements in datatypes, a migration of custom datatypes is needed. Studio does it automatically when you switch to the new platform version. If you don’t use Studio and your project has custom datatypes registered in
metadata.xml
, addid
attribute to thedatatype
element and set it to the value of theNAME
constant of your datatype class. For example:<datatype id="year" class="com.company.sample.YearDatatype"/>
The
Datatypes
class became a wrapper around theDatatypeRegistry
bean, so now you cannot invoke its methods until the Spring container is fully initialized. If you have initialized datatype instances in fields of Spring beans like this:@Component public class MyBean { // will throw a NPE on start private Datatype<BigDecimal> decimalDatatype = Datatypes.getNN(BigDecimal.class); //... }
you should move the initialization to a place where the Spring container is already initialized, for example:
@Component public class MyBean { @Inject private DatatypeRegistry datatypeRegistry; public void myMethod(BigDecimal value) { Datatype<BigDecimal> decimalDatatype = datatypeRegistry.getNN(BigDecimal.class); //... }
-
RemoveAction and
BulkEditAction
do not haveremove
andupdate
constraint operation types by default anymore. The reason is as follows: constraint scripts are normally executed on middleware and expect entities in the managed state. But when you assign a constraint operation type on an action, the same scripts are executed also on the client with detached entities, which may result in unexpected "unfetched attribute" errors. So it should be a developer’s decision whether to assign constraint operation types to actions and hence execute constraint scripts on the client side. -
UserSessionEntity
now contains user login in lower case for reliable identification. -
In the charts add-on, types of the following parameters have been changed:
-
plotAreaFillColors
parameter ofSerialChart
,GanttChart
,XYChart
andStockPanel
hasList<Color>
type. -
fillColors
andnegativeFillColors
parameters ofSerialChart
,GanttChart
,XYChart
,RadarChart
andStockGraph
haveList<Color>
type. -
compareGraphFillColors
parameter ofStockGraph
hasList<Color>
type. -
startDuration
parameter ofHasStartEffect
hasDouble
type. -
minorTickInterval
parameter ofGaugeAxis
hasDouble
type.
-
-
The charts add-on does not provide artifact
com.haulmont.charts:charts-web@web
anymore. If you used it explicitly in yourbuild.gradle
then remove the following dependency:webcontent(group: 'com.haulmont.charts', name: 'charts-web', version: cubaVersion, classifier: 'web', ext: 'zip')
-
The buildWar and buildUberJar tasks get Polymer UI from the
es6-unbundled
directory which is a default for the new Polymer build system. If you have Polymer UI in your project, and you build WAR or UberJAR, you should add the following parameter to the build task until you migrate to Polymer 2:task buildWar(type: CubaWarBuilding) { // ... polymerBuildDir = 'bundled' }
Data Model
Base Classes
Non-persistent entities should be inherited form the same base classes as persistent ones: BaseUuidEntity
, BaseLongIdEntity
, and so on. It allows you to have identifiers of any type, which is important when non-persistent entities represent data from some data store. The framework determines if the entity is persistent or not by the file where it is registered: persistence.xml
or metadata.xml
.
AbstractNotPersistentEntity
has been deprecated, but can still be used for backward compatibility.
Number Format
Using the new @NumberFormat annotation, you can define a display format for numeric attributes right in the entity class. So if you need just a specific formatting of an attribute, and don’t need some custom conversion algorithm, then you don’t have to create a Datatype for the attribute. For example, here is an integer number without grouping separators:
@Column(name = "SIMPLE_NUMBER")
@NumberFormat(pattern = "#")
protected Integer simpleNumber;
Datatypes
The datatypes mechanism has been improved for better extensibility.
The getName()
method of the Datatype
interface is deprecated, and implementation classes do not need the NAME
constant. Instead, the id
XML attribute is used when the implementation class is registered.
The getJavaClass()
method of the Datatype
interface now has a default implementation that returns a value of the @JavaClass
annotation if it is present on the class.
All datatypes are registered in metadata.xml
files, but if old datatypes.xml
exists, it is loaded for backward compatibility.
There is no hard-coded list of "standard datatypes" anymore. The default
XML attribute in metadata.xml
indicates that the datatype should be used by default for a Java class handled by this datatype, i.e. this datatype will be resolved automatically for entity attributes of appropriate type. Standard datatypes are defined in the cuba-metadata.xml
of the cuba
application component. Subsequent metadata.xml
files can add and override any datatype including default ones.
The Datatypes
class became a thin wrapper delegating to the DatatypeRegistry
and FormatStringsRegistry
beans. It is recommended to use DatatypeRegistry
directly. Its getId*()
methods are designed to get an id the datatype is registered with.
Base View
Sometimes _minimal
view includes reference attributes that are not included to _local
, so we have added one more predefined view which is available for all entities: _base
(defined also in View.BASE
constant). It includes all local non-system attributes and attributes defined by @NamePattern
(effectively _minimal
+ _local
).
Generic UI
Lookup Screen Customization
When a browse screen is opened as a lookup, it contains an automatically added panel with buttons and a special lookup action. Now you can customize all these parts: replace the frame with buttons for all lookup screens in your project, create your own selection buttons for a certain screen, or customize the lookup action. See details in the documentation.
Controller of Combined Screen
The framework now contains a base class for controllers of combined screens that are created by the Entity combined screen template in Studio. The base class encapsulates all logic of the screen, so concrete screens have no boilerplate code at all. Also, unlike the previous implementation, the base controller provides pessimistic locking in the same way as AbstractEditor
does.
PopupButton
The PopupButton
component can show not only actions but also custom popup content. For this, the popup
nested XML element or the corresponding popupContent
API property must contain a single Component
or Container
. See details in the documentation.
SuggestionPickerField
To simplify usage of the SuggestionPickerField
component, we have added a declarative way of providing options for the current user input. It’s the query element, containing a JPQL query for loading options from the database.
BrowserFrame
The new BrowserFrame component is designed to display embedded web pages. It is an equivalent of the HTML iframe element.
The Embedded
component has been deprecated. Use the Image component for displaying images or BrowserFrame
for embedded web pages.
CurrencyField
The new CurrencyField component is a text field designed for displaying and entering currency values. It has a currency symbol inside the field and is aligned to the right by default.
FTS Conditions in Filter
Previously, the full-text search functionality in the Filter component could be used only by completely replacing the set of structured conditions, i.e. users had to choose whether they want to filter by conditions or by FTS. Now you can use full-text search together with structured conditions: see FTS condition item in the Add condition dialog. It can be particularly useful in predefined filters and application/search folders if you create a set of hidden structured conditions and leave only the FTS condition for users.
Outer Margin in GroupBox
The GroupBox
container can have a margin outside its border. Sometimes it can save you from adding an extra container just to provide a margin.
Valo Styles
tiny
, small
, large
, huge
predefined styles from the Vaadin’s Valo theme can be used in the following UI components: Button
, Label
, TextField
, TextArea
, DateField
(large
are huge
are not supported), LookupField
, PickerField
, LookupPickerField
, SearchPickerField
, SuggestionPickerField
.
Maximized State
A dialog window or a message dialog can be maximized on opening or when they are already shown. It can be done declaratively in screen’s XML:
<dialogMode maximized="true"/>
Or programmatically:
openWindow("windowAlias", WindowManager.OpenType.DIALOG.setMaximized(true));
showMessageDialog("title", "message", MessageType.WARNING.setMaximized(true));
Return a maximized screen to the normal state:
button.setAction(new BaseAction("unmaximize"){
@Override
public void actionPerform(Component component) {
getDialogOptions().setMaximized(false);
}
});
Polymer UI
Polymer 2
Polymer Client and CUBA elements have been updated in order to be compatible with Polymer 2.0 which comes with the following major features:
-
compatibility with custom elements v1 and shadow DOM v1 standards which are agreed to be implemented in most modern browsers;
-
support ES6 class-based syntax for defining elements.
See more about new features on Polymer website.
Changes in Build Process
Dependency on Gulp and gulpfile.js
were removed in favour of direct polymer-cli
usage. By default, Polymer client is targeting browsers with ES6 support, however it’s possible to specify different build target. See details in the documentation.
Manual Migration
Studio does not provide automatic migration, however Polymer templates are compatible with both Polymer 1 and Polymer 2 based clients.
You can migrate your project to Polymer 2 manually by performing the following steps:
-
Update component versions in
bower.json
. Here is the example of components which are used in Polymer 2.0 compatible client"dependencies": { "fetch": "github/fetch#^2.0.2", "polymer": "Polymer/polymer#^2.0.1", "app-route": "PolymerElements/app-route#^2.0.0", "app-layout": "PolymerElements/app-layout#^2.0.1", "iron-lazy-pages": "TimvdLippe/iron-lazy-pages#^2.0.2", "iron-icons": "PolymerElements/iron-icons#^2.0.1", "vaadin-combo-box": "vaadin/vaadin-combo-box#^2.0.0", "vaadin-date-picker": "vaadin/vaadin-date-picker#^2.0.0", "paper-button": "PolymerElements/paper-button#^2.0.0", "paper-input": "PolymerElements/paper-input#^2.0.0", "paper-checkbox": "PolymerElements/paper-checkbox#^2.0.0", "paper-radio-group": "PolymerElements/paper-radio-group#^2.0.0", "paper-radio-button": "PolymerElements/paper-radio-button#^2.0.0", "paper-icon-button": "PolymerElements/paper-icon-button#^2.0.0", "paper-card": "PolymerElements/paper-card#^2.0.0", "paper-toolbar": "PolymerElements/paper-toolbar#^2.0.0", "paper-spinner": "PolymerElements/paper-spinner#^2.0.0", "paper-toast": "PolymerElements/paper-toast#^2.0.0", "paper-listbox": "PolymerElements/paper-listbox#^2.0.0", "paper-item": "PolymerElements/paper-item#^2.0.0", "paper-drawer-panel": "PolymerElements/paper-drawer-panel#^2.0.0", "paper-header-panel": "PolymerElements/paper-header-panel#^2.0.0", "paper-dropdown-menu": "PolymerElements/paper-dropdown-menu#^2.0.0", "cuba-app": "cuba-elements/cuba-app#^0.3.0", "cuba-data": "cuba-elements/cuba-data#^0.3.0", "cuba-form": "cuba-elements/cuba-form#^0.4.0", "cuba-login": "cuba-elements/cuba-login#^0.3.0", "cuba-styles": "cuba-elements/cuba-styles#^0.3.0", "cuba-ui": "cuba-elements/cuba-ui#^0.3.0", "cuba-file-field": "cuba-elements/cuba-file-field#^0.3.0", "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0", "web-animations-js": "web-animations/web-animations-js#^2.3.1" }
-
Change
scripts
anddevDependencies
inpackage.json
:"scripts": { "build": "polymer build" }, "devDependencies": { "bower": "^1.8.2", "polymer-cli": "^1.5.7" },
-
Change
extraDependencies
andbuild
properties inpolymer.json
:"extraDependencies": [ "manifest.json", "service-worker.js", "bower_components/webcomponentsjs/*.js", "bower_components/fetch/fetch.js" ], "builds": [ { "preset": "es6-unbundled", "basePath": "/app-front/", "addServiceWorker": false } ]
-
Change
assemble
anddeploy
tasks inbuild.gradle
:configure(polymerClientModule) { ... def frontAppDir = 'app-front' ... task assemble(type: NodeTask, dependsOn: installBowerPackages) { script = file("node_modules/polymer-cli/bin/polymer") args = ['build'] inputs.dir "./" outputs.dir "build" } task deployUnbundled(type: Copy) { from file('./') include 'bower_components/**' include 'src/**' into "$cuba.tomcat.dir/webapps/$frontAppDir" } task deploy(type: Copy, dependsOn: [assemble, deployUnbundled]) { from file('build/es6-unbundled') into "$cuba.tomcat.dir/webapps/$frontAppDir" }
-
Open
index.html
and delete webcomponents polyfill loading code:var onload = function() { // For native Imports, manually fire WebComponentsReady so user code // can use the same code path for native and polyfill'd imports. if (!window.HTMLImports) { document.dispatchEvent( new CustomEvent('WebComponentsReady', {bubbles: true}) ); } }; var webComponentsSupported = ( 'registerElement' in document && 'import' in document.createElement('link') && 'content' in document.createElement('template') ); if (!webComponentsSupported) { var script = document.createElement('script'); script.async = true; script.src = 'bower_components/webcomponentsjs/webcomponents-lite.min.js'; script.onload = onload; document.head.appendChild(script); } else { onload(); }
Instead of the code above
webcomponents-loader
should be used now. Paste the script below inside thehead
tag:<script src="bower_components/webcomponentsjs/webcomponents-loader.js"></script>
-
There are no
paper-elements
bundle for Polymer 2.0 so it’s required to import each paper-* element used in app separately. Openapp-shell.html
and change<link rel="import" href="../bower_components/paper-elements/paper-elements.html">
to
<link rel="import" href="../bower_components/paper-button/paper-button.html"> <link rel="import" href="../bower_components/paper-input/paper-input.html"> <link rel="import" href="../bower_components/paper-checkbox/paper-checkbox.html"> <link rel="import" href="../bower_components/paper-radio-group/paper-radio-group.html"> <link rel="import" href="../bower_components/paper-radio-button/paper-radio-button.html"> <link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html"> <link rel="import" href="../bower_components/paper-card/paper-card.html"> <link rel="import" href="../bower_components/paper-toolbar/paper-toolbar.html"> <link rel="import" href="../bower_components/paper-spinner/paper-spinner.html"> <link rel="import" href="../bower_components/paper-toast/paper-toast.html"> <link rel="import" href="../bower_components/paper-listbox/paper-listbox.html"> <link rel="import" href="../bower_components/paper-drawer-panel/paper-drawer-panel.html"> <link rel="import" href="../bower_components/paper-header-panel/paper-header-panel.html"> <link rel="import" href="../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
-
One of the main breaking changes of Polymer 2 is using
slot
instead ofcontent
tags. So we need to explicitly specifyslot
for nested elements e.g.:<paper-drawer-panel id="drawerPanel"> <paper-header-panel drawer> <paper-toolbar> ... <paper-header-panel main> <paper-toolbar class="main-toolbar">
should be
<paper-drawer-panel id="drawerPanel"> <paper-header-panel slot="drawer"> <paper-toolbar slot="header"> ... <paper-header-panel slot="main"> <paper-toolbar slot="header" class="main-toolbar">
You may also want to use app-layout elements instead of deprecated
paper-*
layout elements. -
Pages included in
iron-lazy-pages
should not be wrapped withtemplate
anymore, change:<iron-lazy-pages selected="[[_computeSelectedPage(routeData.page)]]" attr-for-selected="data-route" class="content fit"> <template is="iron-lazy-page" data-route=""> <myapp-page></myapp-page> </template> </iron-lazy-pages>
to
<iron-lazy-pages selected="[[_computeSelectedPage(routeData.page)]]" attr-for-selected="data-route" selected-attribute="active" class="content fit"> <myapp-page data-route=""></myapp-page> </iron-lazy-pages>
Also in order to migrate your own component see the full Polymer upgrade guide
Remove the following directories:
-
.gradle
-
modules/polymer-client/.gradle
-
modules/polymer-client/bower_components/
-
modules/polymer-client/node_modules/
and kill gradle daemon before running the upgraded application.
REST API
LDAP Authentication in REST API
REST API now supports external authentication via LDAP. See documentation for details.
Entities Search Filter
You apply filters when loading lists of entities using the entities operation. See documentation for details.
Reporting
New Templates and Output Types
CUBA report generator now supports the following new templates and output types:
-
JasperReports templates allow you to output reports in PDF, HTML and office formats using the open-source JasperReports library.
-
CSV templates allow you to output reports in the CSV format.
-
Table formatter allows you to output reports into tables right inside your application UI. You don’t need to create and upload any templates, just create the report structure and specify Table in the Output type field of the Template editor screen.
Input Parameters Validation
Before executing a report, its input parameters can be validated using Groovy scripts.
JSON Dataset
The new JSON dataset can be used in the report structure. It allows you to specify the set of records in JSON format. The JSON content can be received from a report parameter, an external URL, or generated by a Groovy script.
DOCX Conversion
Reports with DOCX templates can be output to PDF and HTML using LibreOffice, which provides better quality than default conversion using Docx4j. Use the reporting.openoffice.docx.useOfficeForDocumentConversion application property to specify the conversion mode.
Miscellaneous
Events
The new events mechanism is based on Spring application events and adds ability to send events to screens currently opened by the user.
Entity Log
The entity log mechanism now registers and shows old values of changed attributes.
Entity Attribute Access Control
The security subsystem allows you to set up access to entity attributes according to user permissions. But sometimes you may want to change the access to attributes dynamically depending also on the current state of the entity or its linked entities. The new mechanism allows you to create rules of what attributes should be hidden, read-only or required for a particular entity instance, and apply these rules automatically to Generic UI components and REST API. See details in the documentation.
Accordance With View
The EntityStates
bean now contains a set of methods that allow you to check if an entity instance has attributes loaded according to a view: checkLoadedWithView()
and isLoadedWithView()
. You can use these methods to decide whether you need to reload an instance in some business logic.
The @RequiredView annotation can be added to service method definitions to ensure that entity instances are loaded with all the attributes specified in a view.
Support for Microsoft SQL Server 2005
Now you can connect to Microsoft SQL Server 2005 databases using the jTDS JDBC driver. It will be selected if you specify Microsoft SQL Server 2005 database type for your project’s main or additional data store in Studio.
If you don’t use Studio, specify the following parameters for the createDb
and updateDb
Gradle tasks:
dbms = 'mssql'
dbmsVersion = '2005'
and the following connection parameters in context.xml
:
<Resource
name="jdbc/CubaDS"
type="javax.sql.DataSource"
maxIdle="2"
maxTotal="20"
maxWaitMillis="5000"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
username="sa"
password="saPass1"
url="jdbc:jtds:sqlserver://localhost/sample"/>
Updated Dependencies
Java libraries:
com.esotericsoftware/kryo-shaded = 4.0.1 com.fasterxml.jackson = 2.9.0 com.google.code.gson/gson = 2.8.1 com.haulmont.thirdparty/eclipselink = 2.6.2.cuba18 com.haulmont.yarg = 2.0.7 com.microsoft.sqlserver/mssql-jdbc = 6.2.1.jre8 com.vaadin = 7.7.10.cuba.9 com.vaadin.addon/vaadin-context-menu = 0.7.5 commons-cli/commons-cli = 1.4 commons-fileupload/commons-fileupload = 1.3.3 commons-io/commons-io = 2.5 org.apache.commons/commons-collections4 = 4.1 org.apache.commons/commons-compress = 1.14 org.codehaus.groovy/groovy-all = 2.4.12 org.javassist/javassist = 3.21.0-GA org.springframework = 4.3.10.RELEASE org.springframework.security = 4.2.3.RELEASE org.springframework.security.oauth/spring-security-oauth2 = 2.1.1.RELEASE org.thymeleaf = 3.0.7.RELEASE org.vaadin.addons/popupbutton = 2.6.0-3 org.webjars/amcharts = 3.20.20 org.webjars/pivottable = 2.3.0
Studio
Settings
Most of the Studio settings were moved from the Studio Server window to the Settings tab of the web interface initial screen. So the Studio Server window now contains only settings that really need a restart:
Other settings are available after the start on the Settings tab:
Repository Configuration
Now Studio can manage multiple repositories used in your project. The repository configuration dialog is split into two sections:
The first section contains the list of repositories known to Studio, with their URLs and credentials. This list is stored in the ${user.home}/.haulmont/studio/cache/base-projects.xml
file. Please note that repository passwords are saved in plain text. Initially the list contains only the CUBA public repositories, and you can add your own.
The second section contains repositories selected for the current project. You can add and remove items in this list using the Use in the project and Remove from the project buttons. The Up/Down buttons allow you to order the repositories in your build.gradle
. The order of repositories affects the sequence of searching for platform versions, so we recommend placing a repository containing the platform artifacts on top.
Screen Layout Designer
The screen layout designer has acquired new functionality. First of all, it is Undo and Redo actions that can be invoked using the icon buttons at the top left corner:
The designer now analyzes the screen layout on save and reports about possible issues. In case of a "false positive", you can switch off the analysis for a particular screen in the issue dialog. The icon button at the top right corner indicates whether the analysis is active for the screen, and you can switch it on and off.
Style names of visual components can be selected from the list of predefined styles, see the "plus" button in the stylename field:
Entity Designer
-
Previously, the
@OnDelete
and@OnDeleteInverse
annotations were used only at runtime when processing deletion of soft deleted entities. Now you can define the@OnDeleteInverse
annotation also for a reference to a hard deleted entity, and Studio will create an appropriateon delete
clause for the foreign key on the database level. -
Using the Hide properties link at the top of the entity designer, you can collapse the entity properties panel and give more vertical space to the list of attributes. In the collapsed state, the link changes its title and shows the entity name:
-
If the entity class implements system interfaces like
Creatable
orVersioned
itself (i.e. it does not extendStandardEntity
), it contains appropriate fields:createTs
,createdBy
and so on. Now Studio shows them in the attributes table, and you can arrange them using the Up/Down buttons: -
The Studio entity designer can create method-based non-persistent attributes. If you select Transient checkbox and deselect Create field, the attribute becomes read-only:
The source code of the attribute will look as follows:
@MetaProperty(related = {"name", "num"}) public String getTitle() { return name + " - " + num; // written manually }
-
For reference attributes, the attribute type field contains a button that allows you to navigate to the linked entity:
You can go back using the History dialog that is available via Ctrl-Shift-H or Alt-C shortcuts.