JavaFX global scene variable unexpectedly changed to null - nullpointerexception

I want to make an application in javaFX 2 which opens as a smaller login window, then, when you put in correct data, it takes you to bigger main window. Both are designed in fxml and events are handled within java code.
Yes, I know, it is almost the same as the application in samples and I've tried to do what I want and it worked there.
Now, when I did the same in my project, I hit a problem when I want to change the value of stage.
As you can see in the code below, I have global variable and I set the value of primaryStage in start method to it. Just as a test, I print it out at end of start method and the value is set.
Then, when I try to use it when button is clicked(method buttonClick), the value of stage variable is null, therefore I cannot use it to resize window or anything else.
My question is why is stage variable value reseted despite that I don't use change anything between the two prints?
This code is sample of what I've tried, I've just cut out all code which is not crucial to understand how my application works.
public class App extends Application {
private Stage stage;
#FXML
private AnchorPane pane;
#Override
public void start(Stage primaryStage) {
try {
stage = primaryStage; // Set the value of primaryStage to stage
primaryStage.setScene(new Scene(openScene("Login"))); // Load Login window
primaryStage.show(); // Show the scene
} catch (IOException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(stage);// <-- Here it has the value of primaryStage obviously
}
#FXML
void buttonClick(ActionEvent event) throws IOException {
// Note that even if I try to print here, the value of stage is still
// null, so the code doesn't affect it
// Also, this loads what I want, I just can't change the size.
try{
pane.getChildren().clear(); // Clear currently displayed content
pane.getChildren().add(openScene("MainScene")); // Display new content
System.out.println(stage); // <-- Here, output is null, but I don't know why
stage.setWidth(500); // This line throws error because stage = null
} catch (IOException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
}
public Parent openScene(String name) throws IOException {
//Code from FXML login example
Parent parent = (Parent) FXMLLoader.load(PrijavnoOkno.class.getResource(name
+ ".fxml"), null, new JavaFXBuilderFactory());
return parent;
}
public static void main(String[] args) {
launch(args);
}
}

Although it is not clear by whom and where the buttonClick action method is called, I pressume it is a login button's action in Login.fxml. Also I assume you have defined the App (a.k.a PrijavnoOkno) as a controller of this Login.fxml.
According to these assumptions, there are 2 instances of App.class:
one created when the app starts up and where the stage variable is assigned with primary stage in start() method,
and another instance created by FXMLLoader (while loading Login.fxml) and where the stage variable is not assigned and thus NPE.
One of the right ways can be, create a new Controller class for Login.fxml, call your login action in it. Access the global stage (by making it static in App) from there.

Related

Is there a way wait for code to take effect before a "notify" method is called (E.G. notifyItemRangeInserted) on a Recycler view?

I want to show a progress dialog screen in my app whenever a recycler view begins to load more items. The problem is: I can't get to show the dialog screen because the notify method is ALWAYS executed (and freezes the screen) before the loading screen shows up. Happens even if the "show()" method for it is called in the very first line of my "addContacts()" method.
I've already tried:
getActivity().runOnUiThread();
creating a Thread, starting it, calling join()
starting it with executors
public void addContactsToScreen() {
((BaseActivity) lcf.getActivity()).showProgressDialog();
try {
int currentSize = contactsLoaded.size();
int inserted;
for (inserted = 0;
inserted < DEFAULT_ITEM_INSERTION
&& inserted < lcf.getController().getContacts().size()
&& contactsLoaded.size() < lcf.getController().getContacts().size()
; inserted++) {
contactsLoaded.add(lcf.getController().getContacts().get(currentSize + inserted));
}
if (inserted > 0) {
notifyItemRangeInserted(contactsLoaded.size() - 1, inserted);
}
lcf.getContactsRecycler().getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
lcf.isLoading=false;
lcf.getContactsRecycler().post(new Runnable() {
#Override
public void run() {
((BaseActivity) lcf.getActivity()).hideProgressDialog();
}
});
lcf.getContactsRecycler().getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
That is the original code (no threads or failed attempts). The void is called everytime I initialize the adapter or the view reaches a threshold limit. It loads a list that ends up being shown on screen after "notifyItemRangeInserted()" is called. As you can see the VERY FIRST LINE tries to show the loading screen but for some reason, in the debugger itself I find with breakpoints that the method calls the show method, but the loading screen never appears, fills the list in the "for" loop, calls the notify event, the screen freezes, THEN the loading screen finally shows up but then immediately the hide method is called (rendering teh loading screen useless)
Did you try post runnable method?
progressbar.setvisibility(view.visible);
progressbar.post(new Runnable() {
#Override
public void run() {
fetchMoreDataInTheRecyclerView();
}
});
*Now do the fetching inside fetchMoreDataInTheRecyclerView(); and once done simply make progressbar invisible.
Let me know if this helps.

How to persist/read-back Run Configuration parameters in Intellij plugin

I'm making a basic IntelliJ plugin that lets a user define Run Configuration (following the tutorial at [1]), and use said Run Configurations to execute the file open in the editor on a remote server.
My Run Configuration is simple (3 text fields), and I have it all working, however, after editing the Run Configuration, and click "Apply" or "OK" after changing values, the entered values are lost.
What is the correct way to persist and read-back values (both when the Run Configuration is re-opened as well as when the Run Configuration's Runner invoked)? It looks like I could try to create a custom persistence using [2], however, it seems like the Plugin framework should have a way to handle this already or at least hooks for when Apply/OK is pressed.
[1] https://www.jetbrains.org/intellij/sdk/docs/tutorials/run_configurations.html
[2] https://www.jetbrains.org/intellij/sdk/docs/basics/persisting_state_of_components.html
Hopefully, this post is a bit more clear to those new to IntelliJ plugin development and illustrates how persisting/loading Run Configurations can be achieved. Please read through the code comments as this is where much of the explanation takes place.
Also now that SettingsEditorImpl is my custom implementation of the SettingsEditor abstract class, and likewise, RunConfigurationImpl is my custom implementation of the RunConfigiration abstract class.
The first thing to do is to expose the form fields via custom getters on your SettingsEditorImpl (ie. getHost())
public class SettingsEditorImpl extends SettingsEditor<RunConfigurationImpl> {
private JPanel configurationPanel; // This is the outer-most JPanel
private JTextField hostJTextField;
public SettingsEditorImpl() {
super();
}
#NotNull
#Override
protected JComponent createEditor() {
return configurationPanel;
}
/* Gets the Form fields value */
private String getHost() {
return hostJTextField.getText();
}
/* Copy value FROM your custom runConfiguration back INTO the Form UI; This is to load previously saved values into the Form when it's opened. */
#Override
protected void resetEditorFrom(RunConfigurationImpl runConfiguration) {
hostJTextField.setText(StringUtils.defaultIfBlank(runConfiguration.getHost(), RUN_CONFIGURATION_HOST_DEFAULT));
}
/* Sync the value from the Form UI INTO the RunConfiguration which is what the rest of your code will interact with. This requires a way to set this value on your custom RunConfiguration, ie. RunConfigurationImpl##setHost(host) */
#Override
protected void applyEditorTo(RunConfigurationImpl runConfiguration) throws ConfigurationException {
runConfiguration.setHost(getHost());
}
}
So now, the custom SettingsEditor, which backs the Form UI, is set up to Sync field values In and Out of itself. Remember, the custom RunConfiguration is what is going to actually represent this configuration; the SettingsEditor implementation just represents the FORM (a subtle difference, but important).
Now we need a custom RunConfiguration ...
/* Annotate the class with #State and #Storage, which is used to define how this RunConfiguration's data will be persisted/loaded. */
#State(
name = Constants.PLUGIN_NAME,
storages = {#Storage(Constants.PLUGIN_NAME + "__run-configuration.xml")}
)
public class RunConfigurationImpl extends RunConfigurationBase {
// Its good to 'namespace' keys to your component;
public static final String KEY_HOST = Constants.PLUGIN_NAME + ".host";
private String host;
public RunConfigurationImpl(Project project, ConfigurationFactory factory, String name) {
super(project, factory, name);
}
/* Return an instances of the custom SettingsEditor ... see class defined above */
#NotNull
#Override
public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return new SettingsEditorImpl();
}
/* Return null, else we'll get a Startup/Connection tab in our Run Configuration UI in IntelliJ */
#Nullable
#Override
public SettingsEditor<ConfigurationPerRunnerSettings> getRunnerSettingsEditor(ProgramRunner runner) {
return null;
}
/* This is a pretty cool method. Every time SettingsEditor#applyEditorTo() is changed the values in this class, this method is run and can check/validate any fields! If RuntimeConfigurationException is thrown, the exceptions message is shown at the bottom of the Run Configuration UI in IntelliJ! */
#Override
public void checkConfiguration() throws RuntimeConfigurationException {
if (!StringUtils.startsWithAny(getHost(), "http://", "https://")) {
throw new RuntimeConfigurationException("Invalid host");
}
}
#Nullable
#Override
public RunProfileState getState(#NotNull Executor executor, #NotNull ExecutionEnvironment executionEnvironment) throws ExecutionException {
return null;
}
/* This READS any prior persisted configuration from the State/Storage defined by this classes annotations ... see above.
You must manually read and populate the fields using JDOMExternalizerUtil.readField(..).
This method is invoked at the "right time" by the plugin framework. You dont need to call this.
*/
#Override
public void readExternal(Element element) throws InvalidDataException {
super.readExternal(element);
host = JDOMExternalizerUtil.readField(element, KEY_HOST);
}
/* This WRITES/persists configurations TO the State/Storage defined by this classes annotations ... see above.
You must manually read and populate the fields using JDOMExternalizerUtil.writeField(..).
This method is invoked at the "right time" by the plugin framework. You dont need to call this.
*/
#Override
public void writeExternal(Element element) throws WriteExternalException {
super.writeExternal(element);
JDOMExternalizerUtil.writeField(element, KEY_HOST, host);
}
/* This method is what's used by the rest of the plugin code to access the configured 'host' value. The host field (variable) is written by
1. when writeExternal(..) loads a value from a persisted config.
2. when SettingsEditor#applyEditorTo(..) is called when the Form itself changes.
*/
public String getHost() {
return host;
}
/* This method sets the value, and is primarily used by the custom SettingEditor's SettingsEditor#applyEditorTo(..) method call */
public void setHost(String host) {
this.host = host;
}
}
To read these configuration values elsewhere, say for example a custom ProgramRunner, you would do something like:
final RunConfigurationImpl runConfiguration = (RunConfigurationImpl) executionEnvironment.getRunnerAndConfigurationSettings().getConfiguration();
runConfiguration.getHost(); // Returns the configured host value
See com.intellij.execution.configurations.RunConfigurationBase#readExternal as well as com.intellij.execution.configurations.RunConfigurationBase#loadState and com.intellij.execution.configurations.RunConfigurationBase#writeExternal

Getting Tab parameters inside LaunchConfigurationDelegate

I have a custom launch configuration. It currently has a JavaArgumentsTab() where I can enter things for VM arguments and Program arguments. But how do I actually get any values entered there?
Ideally I would get them inside my LaunchConfigurationDelegate's launch() method. I expected to find any text entered as arguments inside the LaunchConfiguration or other parameters to that method, and I'm sure this is a newbie question, but I really haven't found anything promising.
TabGroup:
public class LaunchConfigurationTabGroup extends AbstractLaunchConfigurationTabGroup {
#Override
public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
new JavaArgumentsTab(),
new CommonTab()
};
setTabs(tabs);
} }
LaunchConfigurationDelegate:
public class LaunchConfigurationDelegate implements ILaunchConfigurationDelegate {
#Override
public void launch(ILaunchConfiguration configuration, String mode,
ILaunch launch, IProgressMonitor monitor) throws CoreException {
// How to get anything entered on my Java tab here...?
} }
Everything from the tabs should already have been set as attribute values in the ILaunchConfiguration when launch is called.
The settings from JavaArgumentsTab are stored in the attributes using constants from IJavaLaunchConfigurationConstants.

Flow of initializing objects in XAML?

I'm not sure but from my hours of debugging, this should be the best description of my problem I can give.
I'm creating a WinRT app, there are two pages- Main Page and Details Page. Inside Main Page constructor, I have initialized a listbox. On click of any of the element of listbox, user is taken to the Details page.
I'm just learning all this and design may not be best but here is what I did.
I took a static variable in MainPage.cs, and set it to point to the element which is clicked by the user. Now in the constructor of the Details page, I used this static variable to set the datacontext of Details Page itself.
What flow I'm expecting is:-
MainPage is created first. Listbox is setup.
User will click on any of the element of listbox. Itemclick event handler runs. It will set the static variable (of Mainpage.cs) to hold the infomation which item is clicked and navigate user to the Details page.
In Details page constructor, I have set the datacontext to point to some information based on the value of static variable mentioned in the previous step.
It works for most of the times, but once in like every 5 times, The Details page constructor throws an exception stating the static variable is not initialized yet. Why is Details page's constructor running when I'm starting the app? and why only sometimes? Do I need to set DataContext of Details Page in some other method instead of constructor?
The code is somewhat complex and too much in terms of domain of the problem so I'm avoiding posting it. But if I'm failing to explain the problem please tell, I'll post it keeping it as related as I can.
CODE:-
This is the method called when an item in listbox is clicked--will take user to the Details page.
private void overviewlistbox_Tapped_1(object sender, TappedRoutedEventArgs e)
{
MatchOverview selectedmatch = (sender as ListBox).SelectedItem as MatchOverview;
matchFullDetails = new ObservableCollection<Match>();
foreach (Match m in UpdateController.matchList)
{
if (m.matchDescription == selectedmatch.matchDesc)
{
matchFullDetails.Add(m);
break;
}
}
if(!(matchFullDetails.Count == 0))
this.Frame.Navigate(typeof(Details));
}
This is the constructor for Main Page:-
public static ObservableCollection<Match> matchFullDetails;
public MainPage()
{
matchFullDetails = new ObservableCollection<Match>();
this.InitializeComponent();
UpdateController update = new UpdateController(); // Creating new object will update the overview_list of UpdateController(static list).
overviewlistbox.ItemsSource = UpdateController.overview_list;
}
And this is the code for constructor of details page, where the exception occurs:-
public static ObservableCollection<Match> matchdetails = new ObservableCollection<Match>();
DispatcherTimer dtm_detailspage = null;
public Details()
{
this.InitializeComponent();
matchdetails = MainPage.matchFullDetails; // matchdetails.Last<>() is take because we only need item which is added latest to the collection.
if (matchdetails.Last<Match>().type == "TEST") // Exception is thrown here--Initialization
// error. When I check MainPage.matchFullDetails,
// no data is shown which means its not yet
// initialized. Also the exception is thrown either at
// the start of the app, or when details page is visited. That too once in 4-5 times, not always.
{
matchdetails.Add(matchdetails.First<Match>() as TestMatch);
}
if (matchdetails.Last<Match>().type == "ODI")
{
matchdetails.Add(matchdetails.Last<Match>() as ODIMatch);
}
if (matchdetails.Last<Match>().type == "T20")
{
matchdetails.Add(matchdetails.Last<Match>() as T20Match);
}
}
Exception Screenshot:-
Call Stack data on bug encounter:-
[Cricket Expert.exe!Cricket_Expert.Details.Details() Line 33 + 0x5 bytes
[External Code]
Cricket Expert.exe!Cricket_Expert.Common.SuspensionManager.RestoreFrameNavigationState(Windows.UI.Xaml.Controls.Frame frame) Line 236 + 0x5 bytes
Cricket Expert.exe!Cricket_Expert.Common.SuspensionManager.RestoreAsyn() Line 124 0x8 bytes
Cricket Expert.exe!Cricket_Expert.App.OnLaunched(Windows.ApplicationModel.Activation.LaunchActivatedEventArgs args) Line 74 + 0x5 bytes
[External Code]
MAJOR UPDATE:
I finally found the flaw. If the Details page is still active, and the app is restarted, the problem occurs.
Is there a solution to this problem??
You can pass information on what needs to be displayed on the Details page through the Navigate call and set the DataContext in OnNavigatedTo override to avoid using static variables. Pages don't get created unless you do it specifically e.g. by navigating to one. They might not be recreated if a page has NavigationCacheMode changed from the default (Disabled) so instances of the page can be reused during navigation calls. Ultimately it's hard to say what's wrong but it seems like something in your code and we couldn't help you if you don't share a sample that reproduces the problem.
*EDIT
One way to debug Details being created before MainPage would be to add this code at the beginning of the Details constructor:
if (MainPage.matchFullDetails == null)
{
System.Diagnostics.Debugger.Break();
}
Then look at the Call Stack panel in Visual Studio to see how it gets constructed.
One way to see if matchFullDetails is ever set to null is to search for its assignment (put a cursor on matchFullDetails in Visual Studio code editor and hit Shift+F12).
Another way would be to make matchFullDetails into a property and test it like this:
private static ObservableCollection<Match> _matchFullDetails;
public static ObservableCollection<Match> matchFullDetails
{
get
{
return _matchFullDetails;
}
set
{
if (value == null)
{
System.Diagnostics.Debugger.Break();
}
_matchFullDetails = value;
}
}
*EDIT 2
You can initialize your static property in a static constructor like this:
public static ObservableCollection<Match> matchFullDetails;
static MainPage()
{
matchFullDetails = new ObservableCollection<Match>();
}
public MainPage()
{
this.InitializeComponent();
UpdateController update = new UpdateController(); // Creating new object will update the overview_list of UpdateController(static list).
overviewlistbox.ItemsSource = UpdateController.overview_list;
}
this will prevent the null reference exception but won't fix your problem overall. When your app gets suspended and resumed - you have to restore the full state and it seems like your matchFullDetails collection would need to be serialized and saved to disk when your app gets suspended. Alternatively you might simply ignore the suspension manager call in App.xaml.cs and always start on home page, though that's not a very good experience and I am not sure if it satisfies app certification.

Asynchronous callback - gwt

I am using gwt and postgres for my project. On the front end i have few widgets whose data i am trying to save on to tables at the back-end when i click on "save project" button(this also takes the name for the created project).
In the asynchronous callback part i am setting more than one table. But it is not sending the data properly. I am getting the following error:
org.postgresql.util.PSQLException: ERROR: insert or update on table "entitytype" violates foreign key constraint "entitytype_pname_fkey"
Detail: Key (pname)=(Project Name) is not present in table "project".
But when i do the select statement on project table i can see that the project name is present.
Here is how the callback part looks like:
oksave.addClickHandler(new ClickHandler(){
#Override
public void onClick(ClickEvent event) {
if(erasync == null)
erasync = GWT.create(EntityRelationService.class);
AsyncCallback<Void> callback = new AsyncCallback<Void>(){
#Override
public void onFailure(Throwable caught) {
}
#Override
public void onSuccess(Void result){ }
};
erasync.setProjects(projectname, callback);
for(int i = 0; i < boundaryPanel.getWidgetCount(); i++){
top = new Integer(boundaryPanel.getWidget(i).getAbsoluteTop()).toString();
left = new Integer(boundaryPanel.getWidget(i).getAbsoluteLeft()).toString();
if(widgetTitle.startsWith("ATTR")){
type = "regular";
erasync.setEntityAttribute(name1, name, type, top, left, projectname, callback);
} else{
erasync.setEntityType(name, top, left, projectname, callback);
}
}
}
Question:
Is it wrong to set more than one in the asynchronous callback where all the other tables are dependent on a particular table?
when i say setProjects in the above code isn't it first completed and then moved on to the next one?
Please any input will be greatly appreciated.
Thank you.
With that foreign key constraint, you must make sure the erasync.setProjects(...) has completed before you insert the rest of the stuff.
I suggest doing the erasync.setEntityAttribute(...) magic in (or from) an onsuccess callback instead of jumping right to it.
You're firing several request in which (guessing from the error message) really should be called in sequence.
Any time you call more than one rpc call; try to think that you should be able to rearrange them in any order (because that's allmost what actually happens because they're asynchronous)... If running them in reverse order does not make sense; you cannot fire them sequentially!
Two ways to fix your problem:
Nesting:
service.callFirst(someData, new AsyncCallback<Void> callback = new AsyncCallback<Void>(){
#Override
public void onFailure(Throwable caught) {/*Handle errors*/}
#Override
public void onSuccess(Void result){
service.callSecond(someOtherData, new AsyncCallback<Void> callback = new AsyncCallback<Void>(){
/* onSuccess and onFailure for second callback here */
});
}
});
Or creating one service call that does both (Recommended):
service.callFirstAndSecond(someData, someOtherData, new AsyncCallback<Void> callback = new AsyncCallback<Void>(){
#Override
public void onFailure(Throwable caught) {/*Handle errors*/}
#Override
public void onSuccess(Void result){
/* Handle success */
}
});
The second option is most likely going to be much less messy, as several nested asynch callbacks quickly grows quite wide and confusing, also you make just one request.
Because of nature of Async, don't assume setProjects(...) method will be called on the server before setEntityAttribute or setEntityType.
Personally, I prefer to have a Project class which contains all necessary info, for example:
public class Project{
private String projectName;
private List attributes = new ArrayList();
.. other properties
// Getter & Setter methods
}
Then send to the server in one round trip:
Project project = new Project();
project.setProjectName(..);
// Set other properties
erasync.saveProjects(project, callback);