Releases: sialcasa/mvvmFX
1.7.0
Breaking Changes
- #149: The
mvvmfx-cdi
module now uses CDI in version 2 and is now independend fromWeld
. This means you can also use other CDI implementations like Apache OpenWebBeans.
However, this also means that you have explicitly add such a CDI implementation to your dependencies. If you like to use Weld like before you have to add the dependency toweld-se-core
.
New Features and Improvements
-
#249: It is now possible to define a custom path to a FXML file for a view and this way override the naming conventions of mvvmFX. For this add the new annotation
@FxmlPath("/path/to/your/fxml")
on
your view class. An example can be seen here -
#518: It is now possible to provide multipe resource-bundles when loading a view via
FluentViewLoader
by invoking theFluentViewLoader#resourceBundle
method multiple times. -
#491: The ModelWrapper now also supports mapping of immutable data classes.
-
#498: If the
fx:controller
attribute in a FXML file points to a ViewModel instead of a View class now an exception with meaningful message is thrown to help finding this misconfiguration. -
#503: All our internal unit-tests are now using JUnit 5. #504 Together with this change we've introduced an equivalent of the old
JfxRunner
that can be used in JUnit 5 tests to run them in a JavaFX environment with a JavaFX platform thread at hand. -
#131: It is now possible to register customer builder-factories. This can make using custom controls easier in some situations.
-
#481: The
CompositeValidator
now provides an unmodifiable observable list of all it's sub-validators. This can be used to calculate a percentage of valid/invalid sub-validators. -
#332: Prerior to this release you had to implement a method
public void initialize()
to make mvvmFX invoke this initializer method after dependency injection is done. This confirms to the JavaFX initialize naming-convention. In addition to this it is now also possible to define any method with any visibility in a ViewModel as an initializer-method by using the new annotation@Initialize
. This makes it also possible to have more than one initializer method in a single ViewModel. Existing code with the old naming-convention approach still works.
1.6.0
Breaking Changes
- #454: The validation feature was moved into it's own sub-module. This way it's possible to use the validation classes without importing the whole mvvmFX framework. If you are using the validator you have to add the new dependency to your maven/gradle build script:
<dependency>
<groupId>de.saxsys</groupId>
<artifactId>mvvmfx-validation</artifactId>
<version>1.6.0</version>
</dependency>
The API and packages of the classes haven't changed so everything you have to do to get your build file.
- #308: If using a dependency injection framework you can add
@PostConstruct
to methods to execute setup code after a class was created and has all dependencies injected. However, if you name this method "initialize" in a ViewModel then this conflicts with the initialization logic of the mvvmFX framework. In this case the method will be invoked 2 times. See the wiki for a detailed explanation. In this situation now an exception is thrown. To fix this you have to rename your@PostConstruct
method. This change is potentially a breaking change for some users even though it's unlikely that this combination ever worked properly anyway. Thx to @sideisra for reporting and to @sirwindfield for fixing.
New Features and Improvements
- #381: ViewModels now support a basic lifecycle to react on the event of the view being added to or removed from the Scene. This way you can implement cleanup logic in your ViewModels to prevent possible memory leaks.
See the wiki page for more informations. - #349: Next to the existing CDI and Guice modules for dependency injection there is now a new module for the EasyDI dependency injection library. EasyDI is a small library for small to medium sized projects. While it's not as powerful as CDI or Guice, it has less configuration overhead and can be much faster then the other two in some situations. Thx to @sirwindfield for the implementation.
- #443: It's now possible to add more complex validation rules to the
ObservableRuleBasedValidator
. Previously it was only possible to add ObservableBoolean rules with a fixed message. Now it's also possible to add anObservable<ValidationMessage>
. This way you can define dynamic messages that are used when the validation fails. See the wiki for a short example. Thx to @gtnarg for the idea. - #423: The ModelWrapper now correctly sets the name attribute of each created JavaFX Property. Thx to @pkantner for the proposal.
- #421: The ModelWrapper now has a method
copyValuesTo
which takes a model instance as argument and copies all current values of the wrapper into the provided model instance. Thx to @pkantner for the proposal. - #345: The
ListTransformation
class has amodelList
property which is now renamed tosourceList
. The new name better reflects what the class is doing by using "source" and "target" as terms. The oldmodelList
property is still available but is now marked as deprecated and will be removed in a future version. Thx to @tranquility79 for implementation.
Bugfixes
- #442: The
DelegateCommand
didn't provide access to an exception that was thrown by the executed action when the command was executed in synchronous mode. You can now access such exceptions withDelegateCommand.getException()
method. Thx to @AKreisel for reporting and to @tranquility79 for fixing. - #399: A
DelegateCommand
wasn't able to be restarted properly. Thx to @tfleis for reporting. - #441: It was possible to subscribe to a
NotificationCenter
withnull
as subscriber. Later, whenunsubscribe
is invoked this was resulting in aNullPointerException
. - #435: When a resourceBundle is injected with
@InjectResourceBundle
annotation then an exception should be thrown when no resourceBundle was provided when loading the scene. This wasn't the case anymore due to a regression in the code. - #426: Injecting a Scope
Context
with@InjectContext
wasn't working when an existing ViewModel instance was used for loading the scene. Thx to @sideisra for reporting. - #419: The
ListTransformation
class was using an immutable list internally for the model list in some situations. This was resulting inUnsupportedOperationExcepion
when new model elements are added to the model list, which of cause is a reasonable usage. Now a normal observable ArrayList is used. - #415: With version 1.51. we introduced a regression by changing the implementation hierarchy of the
CompositeValidator
which breaks customValidationMessage
implementations. Thx to @gtnarg for reporting.
Documentation and examples
- #447: The Contacts example was using an old version of ControlsFX which isn't supported on newer JDKs like 102 and 112. Thx to @bekwam
- #446: There is a new example app that shows how to implement asynchronous behavior with Java CompletableFuture.
1.5.2
1.5.1
This is a bugfix release.
ModelWrapper
- #404 A
NullPointerException
was thrown whenuseCurrentValuesAsDefault
is invoked when no model instance is set in the ModelWrapper - #402 When a new model was set the default values were overwritten. Thx to @johnp for fixing.
- #393 When the user created a field of Type
StringProperty
that uses another StringProperty as accessor (instead of simple getter and setter), the default value wasn't applied. Thx to @johnp for fixing.
Validation
- #398 In version 1.5.0 we introduced
equals
andhashCode
methods forValidationMessage
class. This change introduces a problem with theCompositeValidator
when multipe validators were producingValidationMessages
with equal message text and severity. Now the CompositeValidator handles such cases correctly. Thx to @tfleis for reporting.
Other
- #310
DelegateCommand
wasn't executing callbacks for "succeeded" and "failed" when used in synchronous mode.
1.5.0
This version contains many improvements and small features. Additionally we are releasing a first version of our Scopes feature.
New Features
- After a lot of work durring this release cycle we have introduced a first version of our Scopes feature. A Scope is a data context that can be used by multiple components to share common data without tight coupling between each other.
While there are still some open questions and issues with this feature (#383) we have decided to release it so that potential users can try it out and provide feedback. This means the Scopes feature is in BETA state at the moment.
See the wiki for more informations on how to use scopes.
Small Features and Improvements
- #384: The
executable
parameter ofDelegateCommand
is now of typeObservableValue<Boolean>
instead ofObservableBooleanValue
. This can simplify the usage in some use cases. - #286: Introduces
WeakNotificationObserver
. This can be used as wrapper for theNotificationObserver
to prevent memory leaks. This is similar to WeakChangeListener of JavaFX. The usage is described in the wiki. - #369: The
DefaultNotificationCenter
is now public and has a public constructor. This can be useful for testing purposes. - #356: The initialization of an existing ViewModel instance was inconstent between
JavaView
andFxmlView
. When an existing ViewModel instances was passed to theFluentViewLoader
when loading aJavaView
, theinitialize
method of the ViewModel instance was invoked by the framework in previous versions. Now this isn't the case anymore. This behaviour is constistent with the existing behaviour ofFxmlView
s. For users ofJavaView
this may be a breaking change because existing logic that depend on this behaviour may not work anymore. - #350: The
FluentViewLoader
was missing the possibility to provide an existing CodeBehind when loadingJavaView
s. This is now fixed.
ModelWrapper
- #376: The order in which the ModelWrapper commits and reloads values is now deterministic. In the past the order wasn't specified but now can be assumed to be deterministic. Thanks to @sideisra.
- #372: The ModelWrapper now has an additional constructor taking an
ObjectProperty
of the wrapped model type. When the value of the property changes the ModelWrapper will reload it's internal values automatically. Thanks to @sideisra. - #366: The ModelWrapper has now the possibility to update the default values for it's fields. This can be done by calling
useCurrentValuesAsDefaults
method. Thanks to @sideisra.
Validation
- #364: The
ValidationMessage
class has now a proper implementation ofequals
andhashCode
methods which makes testing of validation logic easier. - #359: The
ValidationMessage
class has now a public constructor to support subclassing.
Bugfixes
- #376 Fixed a potential memory leak in the direct notification mechanism between ViewModel and View due to the fact that the ViewModel instance was used as channel identifier.
1.4.1
This release contains some bugfixes:
- [#335] ViewModels were not injected when Guice AOP interceptors were used. Thx to @archislav for reporting and helping to find the issue.
- [#311] exceptions were silently catched when `DelegateCommand' was used in synchronous mode.
- [#319] the injection behaviour between
JavaView
andFxmlView
was inconsistent when no generic ViewModel type was defined. In case ofJavaView
now an exception is thrown to match the behaviour ofFxmlView
s.
1.4.0
This release contains mostly improvements and bugfixes:
Improvements
- [#221] The ModelWrapper now supports mapping for (observable) lists. Thx to @lihop for this contribution.
- [#247] JFX-Testrunner is now integrated in mvvmfx-testing-utils. This util is still in beta state and will be further improved in the future.
- [#275] The
CachedViewModelCellFactory
now supports customization of theViewListCells
. - [#287] The implementation of the
NotificationCenter
can now be replaced with the new MethodNotificationCenterFactory.setNotificationCenter(...)
. This can make testing easier because you can now use a mock notification center. - [#258] The
GCVerifier
had a dependency to the assertJ library. This dependency was removed. - [#293] The
CachedViewModelCellFactory
has now a shortcut method for use cases where the cell is an mvvmFX-View. For example:CachedViewModelCellFactory.createFxmlView(MyView.class);
creates a cellfactory, that loads anMyView
for every cel. - [#303] A new check in the loading mechanism was added. When a View tries to inject a ViewModel with
@InjectViewModel
we now check that the type of the ViewModel matches the declared generic type of the View. - [#269] Maven dependencies are now using the maven dependency management feature. Thx to @tomasz for this contribution.
- [#279] For the mvvmfx-cdi module the dependency to
org.jboss.weld.se:weld-se
was replaced withweld-se-core
asweld-se
is an uber-jar. This should prevent dependency problems when using other libraries that also have dependencies to weld-se. Thx to @tomasz for this contribution.
Bugfixes
- [#281] The ListTransformation util was firing multiple change events when multiple elements where added. This was leading to problems with
FilteredList
. Now only one change event is fired. - [#292] Under some special conditions a new ViewModel instance was created even if an existing instance was provided to the FluentViewLoader.
- [#301] NotificationCenter was throwing a NullPointerException when trying to remove an observer that isn't registered.
Documentation
- [#252] Documentation for the
@InjectViewModel
annotation in combination with dependency injection frameworks was added in the wiki. - [#217] All examples are now restructured. The "examples" directory contains 3 big example applications books-example, contacts-example and todomvc-example. Additionally there is a subdirectory "mini-examples" for the smaller examples like the helloworld app.
1.3.1
This is a small release with two fixes for problems introduced with the last version 1.3.0.
- Due to the fix for #240 some users had breaking unit tests because of a "toolkit not initialized" Exception when publish/subscribe of the ViewModel was part of the JUnit test. We are now checking if there is a JavaFX UI thread present or not. If no UI thread is present (f.e. while running JUnit tests), the notifications will be published on the current thread like it was done before. This way we can support easy unit tests and still make sure that at runtime all notifications are published on the UI thread. (#263)
- Additionally we have introduced a
NotificationTestHelper
that can be used to test notifications. The test helper can even be used for use cases where notifications are send from different threads and it will handle the UI thread accordingly. See the new paragraph in the Wiki for more informations: https://github.com/sialcasa/mvvmFX/wiki/NotificationCenter#testing-notifications - There was a problem with the
getHighestMessage
method of theValidationStatus
class introduced with #194. In some cases inside of ChangeListeners on thevalidProperty
or one of the observable lists of validation messages, thegetHighestMessage
was throwingIndexOutOfBoundException
s. We have now a new implementation for this method that fixes the problems. (#264)
1.3.0
The biggest feature in this release is the support for validation and an extended support for ResourceBundles.
Validation (BETA) (#194)
Docs: https://github.com/sialcasa/mvvmFX/wiki/Validation
- The user can now use
Validator
s to define validation logic in the ViewModel. In the View there areValidationVisualizer
s used to show validation results from the ViewModel in the View. This way the validation logic is separated from UI code and can be tested. - There are 3 validator variants at the moment:
FunctionBasedValidator
,ObservableRuleBasedValidator
andCompositeValidator
- An implementation of a
ValidationVisualizer
is provided that uses the third-party library "ControlsFX" for decoration.
ResourceBundle handling
Docs: https://github.com/sialcasa/mvvmFX/wiki/resource-bundles-i18n
In both cases there is a hierarchy of the bundles so that values from the global resourceBundle are overwritten (if they share the same key) by values from the per-view bundle (the one that is provided to the FluentViewLoader) and these again are overwritten by bundles for fx:included FXML files.
ModelWrapper now has "dirty" and "different" flag (#232)
dirtyProperty
indicates whether a change was done to at least one of the properties of the ModelWrapper instancedifferentProperty
indicates whether the values of the properties of the ModelWrapper are different to the wrapped model instance. In contrast to thedirtyProperty
this flag will switch back tofalse
when the user changes the property value back to the value of the model object.
Bugfixes
- In contrast to the statements in the JavaDoc a notification published directly from the ViewModel wasn't delivered on the UI thread in any case. (#240)