Hi John,
the reason why the logging was introduced is that when selectBinding is
evaluated and there's a null along the way, you don't know where the
actual (null) value comes from. E.g.
Bindings.selectString(insertedMedia, "title") might be null if
insertedMedia.get() == null || insertedMedia.get().getTitle() == null.
The logging helps to identify the cause of the null.
But I understand that when the developer expects the null to be there,
the NPE logs are not legitimate. The plan is to remove the logging for
new select binding methods that will explicitly provide the default
value when some of the steps are null:
https://javafx-jira.kenai.com/browse/RT-26399.
Regards,
-Martin
On 12/13/2013 10:11 PM, John Hendrikx wrote:
Run the following code. It has a simple ObjectProperty that -can- be
null when there is no Media inserted. I want to make a binding that
displays this information to the user, but will display "-no-media-"
if nothing is inserted.
Is it really necessary to spam my logs with fake NPE's when
insertedMedia happens to be null ? This seems like a perfectly valid
use case, and one that has been working fine up until somewhere
halfway through the JavaFX 8 development cycle (and it still works
fine, but now it spams me).
This is not the only spot I have this in my Application.... almost
everything in my Application is dynamically loaded -- user interfaces
are shown to the user before all data is present, which means I have
lots and lots and lots of bindings that will be null for a short while
as they get loaded. Typically this loading occurs on background
threads in order not to choke the Event thread, nor force the user to
look at some waiting screen while Images get decoded, HTTP requests
complete and Database calls get done.
For the life of me I cannot figure out what could be "wrong" with an
ObjectProperty being null when evaluating a Binding. Either make it
catastrophically fail, so this use case is disallowed as it is
obviously somehow super (confusing|dangerous|morally wrong|politicaly
incorrect) or remove this logging which looks deceptively like a real
error, but is not.
The only reasonable workaround I've found is to just replace the
Bindings class with my own which is a bit more frugal with its logging.
I know about when/then/otherwise... it becomes unreadable at several
levels deep, not to mention being completely unnecessary.
--John
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.stage.Stage;
public class BindingTest extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage primaryStage) {
ObjectProperty<Media> insertedMedia = new SimpleObjectProperty<>();
StringBinding x = new StringBinding() {
StringBinding selectString =
Bindings.selectString(insertedMedia, "title");
{
bind(selectString);
}
@Override
protected String computeValue() {
return selectString.get() == null ? "-no-media-" :
selectString.get();
}
};
System.out.println("x = " + x.get());
insertedMedia.set(new Media());
System.out.println("x = " + x.get());
insertedMedia.get().titleProperty().set("B");
System.out.println("x = " + x.get());
insertedMedia.get().titleProperty().set("B2");
System.out.println("x = " + x.get() + " vs. " +
insertedMedia.get().titleProperty().get());
}
public static class Media {
private final StringProperty title = new SimpleStringProperty();
public StringProperty titleProperty() {
return title;
}
public String getTitle() {
return title.get();
}
public void setTitle(String title) {
this.title.set(title);
}
}
}