JabRef 5.2--2020-09-29--2d92025
Linux 4.12.14-lp151.28.67-default amd64
Java 15
Steps to reproduce the behavior:
Log File
java.lang.NullPointerException: Cannot invoke "org.jabref.logic.shared.DatabaseSynchronizer.pullChanges()" because "<local1>" is null
at org.jabref.gui.shared.PullChangesFromSharedAction.lambda$execute$0(Unknown Source) ~[org.jabref:?]
at java.util.Optional.ifPresent(Unknown Source) ~[?:?]
at org.jabref.gui.shared.PullChangesFromSharedAction.execute(Unknown Source) ~[org.jabref:?]
at org.jabref.gui.actions.JabRefAction.lambda$new$2(Unknown Source) ~[org.jabref:?]
at org.controlsfx.control.action.Action.handle(Unknown Source) ~[org.jabref.merged.module:?]
at org.controlsfx.control.action.Action.handle(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source) ~[org.jabref.merged.module:?]
at javafx.event.Event.fireEvent(Unknown Source) ~[org.jabref.merged.module:?]
at javafx.scene.control.MenuItem.fire(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.doSelect(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.scene.control.ContextMenuContent$MenuItemContainer.lambda$createChildren$12(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source) ~[org.jabref.merged.module:?]
at javafx.event.Event.fireEvent(Unknown Source) ~[org.jabref.merged.module:?]
at javafx.scene.Scene$MouseHandler.process(Unknown Source) ~[org.jabref.merged.module:?]
at javafx.scene.Scene.processMouseEvent(Unknown Source) ~[org.jabref.merged.module:?]
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source) ~[org.jabref.merged.module:?]
at java.security.AccessController.doPrivileged(Unknown Source) ~[?:?]
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.glass.ui.View.handleMouseEvent(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.glass.ui.View.notifyMouse(Unknown Source) ~[org.jabref.merged.module:?]
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) ~[org.jabref.merged.module:?]
at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(Unknown Source) ~[org.jabref.merged.module:?]
at java.lang.Thread.run(Unknown Source) [?:?]
The solution would be to create another BooleanExpression in the ActionHelper class, e..g needsSharedDatabase
filter there
And in the action you can then bind it, e..g:
this.executable.bind(ActionHelper.needsEntriesSelected(stateManager));
Hi! Can I work on this?
Sure. Go ahead, if you have any questions ask here or in our gitter channel
Hello I'm back. I think I have a solution almost worked out but I need a little help.
I added the binding in PullChangesFromSharedAction.java
public PullChangesFromSharedAction(StateManager stateManager) {
this.stateManager = stateManager;
this.executable.bind(ActionHelper.needsDatabase(stateManager));
this.executable.bind(ActionHelper.needsSharedDatabase(stateManager)); //new
}
The problem is I'm still not sure how to make the validation in the ActionHelper.java. So far my approach is something like this:
public static BooleanExpression needsSharedDatabase(StateManager stateManager){
return stateManager.activeDatabaseProperty().isEqualTo("shared");
}
The problem is that in the .isEqualTo I'm not sure with what I should compare it to detect when the user is not using a shared database.
I would really appreciate some help to make my first contribution!
Idea is good so far, for checking if it's a shared database you better check the bibdatabasecontect e.g
databaseContext.getLocation() == DatabaseLocation.SHARED)
Bindings.createBooleanBinding is probably your friend here. Be aware that you can combine two Bindings with .and()
Update:
I came up with this solution:
public static BooleanExpression needsSharedDatabase(StateManager stateManager) {
BibDatabaseContext databaseContext = stateManager.activeDatabaseProperty().orElse(null).get();
return Bindings.createBooleanBinding(() -> databaseContext != null && databaseContext.getLocation() == DatabaseLocation.SHARED);
}
But now the problem is that the validation is only being done at the start when I run the program. I'm guessing It's related to the StateManager.java but I'm fairly new to JavaFX so I'll keep looking into it.
You need to add the check for the active database property in the booleanBinding itself. The Bindings are wrapper around Observables. Observables update whenever their values changes.
Some background info: https://docs.oracle.com/javase/8/javafx/properties-binding-tutorial/binding.htm
I think something like this could work:
you may need to add some null checks
var binding = Bindings.createBooleanBinding(()->
stateManager.activeDatabaseProperty().getValue().filter(context->context.getLocation() == DatabaseLocation.SHARED).isPresent(),
stateManager.activeDatabaseProperty());
return BooleanExpression.booleanExpression(binding);
Thanks a lot @Siedlerchr I really appreciate your help. I'll look into it.
orElse(null) is always a bad idea...
Try using .isEmpty() inside the lambda expression.