javabuilders icon indicating copy to clipboard operation
javabuilders copied to clipboard

NPE and other Exception building an int property

Open luca-domenichini opened this issue 9 years ago • 2 comments

Starting from Swing sample PersonApp, if you just add a simple int property to class PersonApp:

[PersonApp.java]
private int number;
public void setNumber(int number) {
    this.number = number;
}
public int getNumber() {
    return number;
}
[PersonApp.yml]
JFrame(name=frame, title=frame.title, size=packed, defaultCloseOperation=exitOnClose):
    - JButton(name=save, text=button.save, onAction=[$validate,save,done])
    - JButton(name=cancel, text=button.cancel, onAction=[$confirm,cancel])
    - MigLayout: |
          [pref]              [grow,100]     [pref]             [grow,100]
          "label.firstName"   txtFirstName   "label.lastName"   txtLastName
          "label.email"       txtEmail+*
          >save+*=1,cancel=1
    - number: 1
bind:
    - txtFirstName.text: person.firstName
    - txtLastName.text: person.lastName
    - txtEmail.text: person.emailAddress
validate:
    - txtFirstName.text: {mandatory: true, label: label.firstName}
    - txtLastName.text: {mandatory: true, label: label.lastName}
    - txtEmail.text: {mandatory: true, emailAddress: true, label: label.email}

results in a NPE

Unable to process property PersonApp.number : null
java.lang.NullPointerException: null
    at org.javabuilders.Builder.handleProperty(Builder.java:862)
    at org.javabuilders.Builder.processDocumentNode(Builder.java:560)
    at org.javabuilders.Builder.processDocumentNode(Builder.java:543)
    at org.javabuilders.Builder.handleType(Builder.java:708)
    at org.javabuilders.Builder.processDocumentNode(Builder.java:510)
    at org.javabuilders.Builder.executeBuild(Builder.java:449)
    at org.javabuilders.Builder.buildFromString(Builder.java:324)
    at org.javabuilders.Builder.build(Builder.java:265)
    at org.javabuilders.Builder.build(Builder.java:185)
    at org.javabuilders.Builder.build(Builder.java:144)
    at org.javabuilders.swing.SwingJavaBuilder.build(SwingJavaBuilder.java:89)
    at person.app.PersonApp.<init>(PersonApp.java:47)
    at person.app.PersonApp$1.run(PersonApp.java:98)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: java.lang.NullPointerException
    at org.javabuilders.Builder.handleProperty(Builder.java:850)
    ... 26 more

changing Buider.java, lines 850 to (bold text) could resolve problem..:

                        String sValue = parent.getStringProperty(currentKey);
                        if (sValue != null && sValue.matches(asValueHandler.getRegex())) {
                            //replace the value from the file with the corresponding object instance
                            parent.getProperties().put(currentKey, asValueHandler.getValue(process, parent, currentKey, 
                                    parent.getProperty(currentKey)));
                        } else {
                            throw new BuildException("Invalid {0} value \"{1}\" for {2}.{3}. Must in be in \"{4}\" format, e.g. \"{5}\"",
                                    propertyType.getSimpleName(), sValue, parent.getMainObject().getClass().getSimpleName(),
                                    currentKey, asValueHandler.getRegex(), asValueHandler.getInputValueSample());
                        }

unfortunately, this does not solve the issue.. the subsequent exception is throws:

Invalid int value "null" for PersonApp.number. Must in be in "\d+|[a-zA-Z0-9_]+" format, e.g. "3 | SOME_CONSTANT_VALUE | someConstantValue"
    at org.javabuilders.Builder.handleProperty(Builder.java:855)
    ... 26 more

My question at this point is, is it possible to use properties other than String in yml files, and assign them to java class?

luca-domenichini avatar Nov 03 '15 11:11 luca-domenichini

I suspect I don't support primitive types. Can you try it with Integer and see if that works?

Also, everything in the "child" document under a JFrame refers to children objects that get added to it and not to properties on the actual JFrame.

Maybe

JFrame(name=frame, title=frame.title, size=packed, defaultCloseOperation=exitOnClose, number=1):

may work, but I am not sure, Never used it on custom properties.

Let me know.

jacek99 avatar Nov 03 '15 14:11 jacek99

Thanks for your interest!

resuming: changing the property to Integer does not results anymore in any exception.

Leaving the definition of the frame as is (I mean as a child, - number = 1) the value is not populated.

Instead, as you suggested, using

JFrame(name=frame, title=frame.title, size=packed, defaultCloseOperation=exitOnClose, number=1):

works as expected.

Maybe, it would be worth adding a check to property "- number = 1" for existence instead of leaving that simply null without any exception reported to user..

what do you think about?

luca-domenichini avatar Nov 03 '15 15:11 luca-domenichini