Faktor-IPS
Release Notes
Version 2.8.2
Version Updates
The following versions have been updated:
| Dependency | New version | Previous version |
|---|---|---|
25.7.3.release (Release Notes) |
25.7.1.release |
|
Vaadin |
24.7.14 (Release Notes) |
24.7.13 |
Spring Boot compatibility tested for |
3.5.7 (Release Notes) |
3.5.5 |
Bugfixes
-
In version
2.8.1, entering a value to a cell inside a table created with@UITableComponentand traversing with the tab-key results in loosing focus. Starting with2.8.2, the behavior has been fixed.
Version 2.8.1
Version Updates
The following versions have been updated:
| Dependency | New version | Previous version |
|---|---|---|
Faktor-IPS |
25.7.1.release (Release Notes) |
25.7.0.release |
Vaadin |
24.7.13 (Release Notes) |
24.7.8 |
Spring Boot compatibility tested for |
3.5.5 (Release Notes) |
3.5.3 |
Bugfixes
-
The linkki-bom was published incorrectly and did not contain any
dependencyManagemententries. This issue affects only version2.8.0. Starting with2.8.1, the BOM has been fixed and works as expected. -
Testing: The annotation
WithLocalenow works correctly with@ParameterizedTest.
Version 2.8.0
The release notes contain changes compared to version 2.7.1.
Version Updates
The following versions have been updated:
| Dependency | New version | Previous version |
|---|---|---|
Java |
21 |
17 |
Faktor-IPS |
25.7.0.release (Release Notes) |
25.1.2.release |
Vaadin |
24.7.8 (Release Notes) |
24.5.12 |
Spring Boot compatibility tested for |
3.5.3 (Release Notes) |
3.4.3 |
The Vaadin version update brings some changes that may affect linkki applications:
-
The supported Node version is changed from 18 to 20.
-
New theme
wraponHorizontalLayoutallowing elements to move to the next line, if there’s no space left. -
Testbench: The method
WebElement#getAttributeis deprecated and should be replaced withWebElement#getDomAttribute.
Integration of linkki-f10 functionalities into linkki
linkki-f10 is a library created by Faktor Zehn that provided additional linkki functionalities that are commonly used in Faktor Zehn products, but are not open source.
With this version, classes in linkki-f10 are fully integrated into linkki, making the code and documentation available at one place.
As part of this transition, all classes in the linkki-f10 module have been deprecated and replaced by corresponding functionality in the other modules of linkki.
In addition to the changes in code, the documentation is now also moved to according sections at doc.linkki-framework.org. During this process, the documentation of the affected components has been reworked.
Migration
This change requires action from all users of linkki-f10 or linkki-f10-search.
The migration mainly consists of package renamings in imports.
Most notable changes:
-
Functionalities previously contained in the
linkki-f10-searchmodule have been moved to the newlinkki-search-vaadin-flowmodule. The maven dependency tolinkki-f10-searchmust be replaced by dependency tolinkki-search-vaadin-flow. The documentation is moved to section "Search" in chapter "UI Components". -
Maven dependency for
linkki-f10is no longer available in newer version. Classes are moved tolinkki-core-vaadin-flow,linkki-application-framework-vaadin-floworlinkki-vaadin-flow-componentdepending on the functionality. -
Most functionalities of
CommonApplicationHeaderare incorporated intoApplicationHeader. Functionalities that are related to the user are implemented in the newly introducedUserAwareApplicationHeaderwith the same API. -
UIMenuListandUIMenuButtonnow have the default valueDERIVED_BY_LINKKIfor caption. Therefore, the attribute caption is not mandatory anymore. Existing declarations that useDERIVED_BY_LINKKIcan be removed. -
The
NavigationWorkaroundis not needed anymore as the underlying Vaadin bug is fixed.
Migration Guide
-
Include dependency to
org.linkki-framework:linkki-f10if it is not used already and use the version2.8.0.
The project should compile successfully at this point as all existing classes are available as-is with this dependency. The existing classes are deprecated and are documented with steps to fix the deprecation warning for each class. -
Include new dependencies if necessary:
-
If
linkki-f10-searchwas used as dependency, replace the dependency with linkki-search-vaadin-flow in version2.8.0. -
Add dependency to
linkki-application-framework-vaadin-flowif it was not used before and either any of the classesInfoTool,InfoToolsComponent,HasBrowserConfirmationwere used, orCommonsApplicationHeaderwas used with the user menu.
-
-
Adjust to API changes:
-
Replace usages of
NavigationWorkaroundbyUI.getCurrent().navigate(). The class is not needed anymore as the underlying Vaadin bug is fixed. -
Replace
CommonsApplicationHeader: if the user menu is not used, useApplicationHeaderdirectly instead. Otherwise, useUserAwareApplicationHeader. Existing declarations that useDERIVED_BY_LINKKIcan be removed.
-
-
Adjust package imports:
-
If the IDE is capable of adding unambiguous missing imports for the whole project (e.g. Eclipse): remove dependency to
linkki-f10and reorganize imports. -
Alternatively, the imports can be adjusted by using the python script provided below by executing the script in the working directory of the project.
-
-
Make sure that dependency to
linkki-f10is removed.
Python migration script
import os
# Mapping of old imports to new imports
import_mapping = {
"de.faktorzehn.commons.linkki.F10ProductTheme": "org.linkki.core.ui.theme.F10ProductTheme",
"de.faktorzehn.commons.linkki.board.BoardComponent": "org.linkki.core.vaadin.component.board.BoardComponent",
"de.faktorzehn.commons.linkki.board.BoardLayout": "org.linkki.core.vaadin.component.board.BoardLayout",
"de.faktorzehn.commons.linkki.ui.menu.UIMenuButton": "org.linkki.core.ui.element.annotation.UIMenuButton",
"de.faktorzehn.commons.linkki.ui.menu.MenuButtonInvokeAspectDefinition": "org.linkki.core.ui.element.annotation.UIMenuButton.MenuButtonInvokeAspectDefinition",
"de.faktorzehn.commons.linkki.ui.menu.UIMenuList": "org.linkki.core.ui.element.annotation.UIMenuList",
"de.faktorzehn.commons.linkki.ui.menu.MenuItemsAspectDefinition": "org.linkki.core.ui.element.annotation.UIMenuList.MenuItemsAspectDefinition",
"de.faktorzehn.commons.linkki.ui.table.HierarchicalTableUtil": "org.linkki.core.ui.table.util.HierarchicalTableUtil",
"de.faktorzehn.commons.linkki.CommonApplicationHeader": "org.linkki.framework.ui.application.UserAwareApplicationHeader",
"de.faktorzehn.commons.linkki.infotool.InfoTool": "org.linkki.framework.ui.component.infotool.InfoTool",
"de.faktorzehn.commons.linkki.infotool.InfoToolsComponent": "org.linkki.framework.ui.component.infotool.InfoToolsComponent",
"de.faktorzehn.commons.linkki.ui.confirm.HasBrowserConfirmation": "org.linkki.framework.ui.HasBrowserConfirmation",
"de.faktorzehn.commons.linkki.ui.menu.SingleItemMenuBar": "org.linkki.core.vaadin.component.menu.SingleItemMenuBar",
"de.faktorzehn.commons.linkki.ui.menu.MenuItemDefinition": "org.linkki.core.vaadin.component.menu.MenuItemDefinition",
"de.faktorzehn.commons.linkki.search.annotation.UISearchLayoutHeadline": "org.linkki.framework.ui.component.UIHeadline",
"de.faktorzehn.commons.linkki.search.annotation.BindSlot": "org.linkki.core.ui.aspects.annotation.BindSlot",
"de.faktorzehn.commons.linkki.search.annotation.NestedPmoMethodLayoutDefinitionCreator": "org.linkki.search.annotation.NestedPmoMethodLayoutDefinitionCreator",
"de.faktorzehn.commons.linkki.search.annotation.SearchInputLayoutDefinitionCreator": "org.linkki.search.annotation.SearchInputLayoutDefinitionCreator",
"de.faktorzehn.commons.linkki.search.annotation.UISearchCriteriaGroup": "org.linkki.search.annotation.UISearchCriteriaGroup",
"de.faktorzehn.commons.linkki.search.annotation.UISearchInputLayout": "org.linkki.search.annotation.UISearchInputLayout",
"de.faktorzehn.commons.linkki.search.annotation.UISearchLayout": "org.linkki.search.annotation.UISearchLayout",
"de.faktorzehn.commons.linkki.search.annotation.UISearchParameters": "org.linkki.search.annotation.UISearchParameters",
"de.faktorzehn.commons.linkki.search.annotation.UISearchResultAction": "org.linkki.search.annotation.UISearchResultAction",
"de.faktorzehn.commons.linkki.search.annotation.UISearchResultLayout": "org.linkki.search.annotation.UISearchResultLayout",
"de.faktorzehn.commons.linkki.search.annotation.UISearchTable": "org.linkki.search.annotation.UISearchTable",
"de.faktorzehn.commons.linkki.search.component.SearchCriteriaGroup": "org.linkki.search.component.SearchCriteriaGroup",
"de.faktorzehn.commons.linkki.search.component.SearchInputLayout": "org.linkki.search.component.SearchInputLayout",
"de.faktorzehn.commons.linkki.search.component.SearchLayout": "org.linkki.search.component.SearchLayout",
"de.faktorzehn.commons.linkki.search.model.RoutingSearchController": "org.linkki.search.model.RoutingSearchController",
"de.faktorzehn.commons.linkki.search.model.SearchController": "org.linkki.search.model.SearchController",
"de.faktorzehn.commons.linkki.search.model.SearchParameterMapper": "org.linkki.search.model.SearchParameterMapper",
"de.faktorzehn.commons.linkki.search.model.SimpleSearchController": "org.linkki.search.model.SimpleSearchController",
"de.faktorzehn.commons.linkki.search.pmo.SearchButtonsPmo": "org.linkki.search.pmo.SearchButtonsPmo",
"de.faktorzehn.commons.linkki.search.pmo.SearchInputPmo": "org.linkki.search.pmo.SearchInputPmo",
"de.faktorzehn.commons.linkki.search.pmo.SearchLayoutPmo": "org.linkki.search.pmo.SearchLayoutPmo",
"de.faktorzehn.commons.linkki.search.pmo.SearchResultPmo": "org.linkki.search.pmo.SearchResultPmo",
"de.faktorzehn.commons.linkki.search.pmo.SearchResultTablePmo": "org.linkki.search.pmo.SearchResultTablePmo",
"de.faktorzehn.commons.linkki.search.util.NlsSearch": "org.linkki.search.util.NlsSearch",
"de.faktorzehn.commons.linkki.search.util.ParamsUtil": "org.linkki.search.util.ParamsUtil",
"de.faktorzehn.commons.linkki.search.SearchLayoutBuilder": "org.linkki.search.SearchLayoutBuilder"
}
def replace_imports_in_file(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
for old_import, new_import in import_mapping.items():
content = content.replace(old_import, new_import)
with open(file_path, 'w', encoding='utf-8') as file:
file.write(content)
def process_directory(directory):
for root, _, files in os.walk(directory):
for file in files:
if file.endswith('.java'): # Assuming Java files
file_path = os.path.join(root, file)
replace_imports_in_file(file_path)
# Get the current working directory
current_directory = os.getcwd()
process_directory(current_directory)
Full list of all changed imports
de.faktorzehn.commons.linkki.F10ProductTheme |
|
de.faktorzehn.commons.linkki.board.BoardComponent |
|
de.faktorzehn.commons.linkki.board.BoardLayout |
|
de.faktorzehn.commons.linkki.ui.menu.UIMenuButton |
|
de.faktorzehn.commons.linkki.ui.menu.MenuButtonInvokeAspectDefinition |
org.linkki.core.ui.element.annotation.UIMenuButton.MenuButtonInvokeAspectDefinition |
de.faktorzehn.commons.linkki.ui.menu.UIMenuList |
|
de.faktorzehn.commons.linkki.ui.menu.MenuItemsAspectDefinition |
org.linkki.core.ui.element.annotation.UIMenuList.MenuItemsAspectDefinition |
de.faktorzehn.commons.linkki.ui.table.HierarchicalTableUtil |
de.faktorzehn.commons.linkki.CommonApplicationHeader |
|
de.faktorzehn.commons.linkki.infotool.InfoTool |
|
de.faktorzehn.commons.linkki.infotool.InfoToolsComponent |
|
de.faktorzehn.commons.linkki.ui.confirm.HasBrowserConfirmation |
de.faktorzehn.commons.linkki.ui.menu.SingleItemMenuBar |
org.linkki.core.vaadin.component.menu.SingleItemMenuBar |
de.faktorzehn.commons.linkki.ui.menu.MenuItemDefinition |
org.linkki.core.vaadin.component.menu.MenuItemDefinition |
de.faktorzehn.commons.linkki.search.annotation.UISearchLayoutHeadline |
|
de.faktorzehn.commons.linkki.search.annotation.BindSlot (deprecated in a previous release, now removed) |
de.faktorzehn.commons.linkki.search.annotation.NestedPmoMethodLayoutDefinitionCreator |
org.linkki.search.annotation.NestedPmoMethodLayoutDefinitionCreator |
de.faktorzehn.commons.linkki.search.annotation.SearchInputLayoutDefinitionCreator |
org.linkki.search.annotation.SearchInputLayoutDefinitionCreator |
de.faktorzehn.commons.linkki.search.annotation.UISearchCriteriaGroup |
org.linkki.search.annotation.UISearchCriteriaGroup |
de.faktorzehn.commons.linkki.search.annotation.UISearchInputLayout |
org.linkki.search.annotation.UISearchInputLayout |
de.faktorzehn.commons.linkki.search.annotation.UISearchLayout |
org.linkki.search.annotation.UISearchLayout |
de.faktorzehn.commons.linkki.search.annotation.UISearchParameters |
org.linkki.search.annotation.UISearchParameters |
de.faktorzehn.commons.linkki.search.annotation.UISearchResultAction |
|
de.faktorzehn.commons.linkki.search.annotation.UISearchResultLayout |
org.linkki.search.annotation.UISearchResultLayout |
de.faktorzehn.commons.linkki.search.annotation.UISearchTable |
org.linkki.search.annotation.UISearchTable |
de.faktorzehn.commons.linkki.search.component.SearchCriteriaGroup |
org.linkki.search.component.SearchCriteriaGroup |
de.faktorzehn.commons.linkki.search.component.SearchInputLayout |
org.linkki.search.component.SearchInputLayout |
de.faktorzehn.commons.linkki.search.component.SearchLayout |
org.linkki.search.component.SearchLayout |
de.faktorzehn.commons.linkki.search.model.RoutingSearchController |
|
de.faktorzehn.commons.linkki.search.model.SearchController |
|
de.faktorzehn.commons.linkki.search.model.SearchParameterMapper |
|
de.faktorzehn.commons.linkki.search.model.SimpleSearchController |
|
de.faktorzehn.commons.linkki.search.pmo.SearchButtonsPmo |
org.linkki.search.pmo.SearchButtonsPmo |
de.faktorzehn.commons.linkki.search.pmo.SearchInputPmo |
org.linkki.search.pmo.SearchInputPmo |
de.faktorzehn.commons.linkki.search.pmo.SearchLayoutPmo |
|
de.faktorzehn.commons.linkki.search.pmo.SearchResultPmo |
org.linkki.search.pmo.SearchResultPmo |
de.faktorzehn.commons.linkki.search.pmo.SearchResultTablePmo |
org.linkki.search.pmo.SearchResultTablePmo |
de.faktorzehn.commons.linkki.search.util.NlsSearch |
org.linkki.search.util.NlsSearch |
de.faktorzehn.commons.linkki.search.util.ParamsUtil |
|
de.faktorzehn.commons.linkki.search.SearchLayoutBuilder |
UI Annotations and Aspects
-
UIHeadline
A new UI component,@UIHeadline, is now available, providing a way to easily create headlines that only display text. -
UIOpenDialogButton
Sometimes, a value or a grid item should not be edited directly. Instead, a dialog should be opened upon a button click in which the user can edit the value in a more complex form. To implement this use case,BindingContext#modelChangedoften needs to be passed to the PMO to update the underlyingBindingContextafter the OK button was clicked.
The new UI annotation @UIOpenDialogButton resolves this inconvenience. The annotated method returns aDialogPmothat is used to create the dialog that is opened upon button click.
For use with a Faktor-IPS model object, the abstract classIpsDialogPmoprovides a partial implementation ofDialogPmo. When the user clicks on the OK button, the underlyingBindingContextis updated automatically.
Alternatively, aFunctioncan be returned that defines how to create a dialog that applies the given handler additionally on OK click. This can be used for use cases where the dialog content cannot be defined as a PMO.Note that this annotation is an experimental feature that may be subject of API change in the near future.
-
UIMenuList and UIButton
New UI components,@UIMenuListand@UIMenuButton, are now available, providing a way to create buttons in menus that can expand a menu list or execute an action, while maintaining a consistent look and feel. -
BindComboBoxItemStyle
@BindComboBoxItemStyle can now be used together with@UIMultiSelect. -
Custom aspects with asynchronously loaded values
It is now possible to create custom aspects that load values asynchronously with aCompletableFuture. The documentation for creating custom aspects is extended with a how-to guide for creating custom future aware aspects.Additionally, the frontend behaviors of
@UILabeland@UITableComponentconsidering loading have been unified. This leads to following breaking changes in the frontend:-
During loading, the
items-loading(UITableComponent) /value-loading(UILabel) attributes are no longer set. Instead, the attributecontent-loadingis set. -
The
has-errorsattribute has been renamed tohas-loading-error. -
The CSS property
error-messageshas been renamed toloading-error-message. -
@UILabelcomponents in a loading state no longer have the CSS classloading.
-
Custom CSS selectors that utilize the above attributes / CSS Properties must be adjusted accordingly.
Testing
-
Conditions for AssertJ
The utility classComponentConditionsproviding UI specific conditions for AssertJ has been added tolinkki-vaadin-flow-testto support writing more readable assertions such asassertThat(component).is(childOf(layout))orassertThat(component).has(anyChildrenSatisfying(…)). -
Component Tree Representation
When using AssertJ, the object that is tested is displayed withtoString()in case of failure. In case of aComponent, it is often not immediately clear how the component actually looks like. The new classComponentTreeRepresentationcan be used withAssertions#withRepresentationto display the component with the complete component tree in case of failure. -
Added Functionalities in KaribuUtils
-
KaribuUtils#getTextContentnow also returns the text content of layout elements. -
The component tree can now be returned without printing it using
KaribuUtils#getComponentTree. -
printComponentTreeandgetComponentTreealso print out all table rows. -
KaribuUtils.Grids.getTextContentInColumnalso returns the value of an input element such as text field. The method also supportsTreeGridnow, but only displays root items. -
Added
KaribuUtils.ComboBoxes#setValueByLabelto set the value within a combobox based on a label. -
Added
KaribuUtils.Dialogs#getFirstMessageto get the component of the first validation message in a OkCancelDialog.
-
-
Method renaming within KaribuUtils.ComboBoxes
Methods inKaribuUtils.ComboBoxesare renamed to make them more consistent to methods inFields:-
getComboBoxWithId→getWithId -
setComboBoxValue→setValue
-
Other Improvements
-
New documentation chapter - How-To
Introduced a How-To chapter containing coding examples and best practises. -
Relocation of UINestedComponent
UINestedComponenthas been moved fromlinkki-core-nestedcomponent-vaadin-flowtolinkki-core-vaadin-flow. The modulelinkki-core-nestedcomponent-vaadin-flowhas been removed. -
New theme variant for form item label alignment
The new theme variantform-item-label-startcan be used to create sections with left aligned labels on form items. The variant can be applied to a single layout using@BindVariantNames. -
New Utility CSS class for nested flex items
The classflex-basis-0sets the initial size of flex items to zero, allowing flex items to grow based only on the available space. It is also available as the constantLinkkiTheme.Flex.BASIS_NONE.
Bugfixes
-
SimpleItemSuppliernow throws aNullPointerExceptionif the model object to PMO mapping supplier returnsnull. -
linkki-vaadin-flow-testno longer includesvaadin-dev, andlinkki-vaadin-flow-testbench-extensionnow marksvaadin-coreas provided. This avoids unwanted dependencies in production.