[committed] In the jME 2 project, MaxToJme main() causes a NullPointerException

I created a issue for this one:

https://jme.dev.java.net/issues/show_bug.cgi?id=281



I wanted to post here as well for two reason.  I don't believe I'm the only one who has seen this and maybe someone could tell me if I'm doing something wrong and after searching the forum, it doesn't look like there are other posts related to this and it might be useful to someone else.



When running MaxToJme main() with the appropriate arguments, execution will fail with the following output:



Oct 25, 2008 11:07:05 AM com.jmex.model.converters.FormatConverter attemptFileConvert

INFO: Converting file C:ProjectsworkspaceBaketf.3DS to C:ProjectsworkspaceBaketf.3DS.jbin

Oct 25, 2008 11:07:07 AM com.jme.system.lwjgl.LWJGLDisplaySystem <init>

INFO: LWJGL Display System created.

Exception in thread "main" java.lang.NullPointerException

at com.jmex.model.converters.maxutils.MaterialBlock.initializeVariables(MaterialBlock.java:80)

at com.jmex.model.converters.maxutils.MaterialBlock.<init>(MaterialBlock.java:75)

at com.jmex.model.converters.maxutils.EditableObjectChunk.processChildChunk(EditableObjectChunk.java:94)

at com.jmex.model.converters.maxutils.ChunkerClass.chunk(ChunkerClass.java:94)

at com.jmex.model.converters.maxutils.EditableObjectChunk.<init>(EditableObjectChunk.java:80)

at com.jmex.model.converters.maxutils.TDSFile.processChildChunk(TDSFile.java:102)

at com.jmex.model.converters.maxutils.ChunkerClass.chunk(ChunkerClass.java:94)

at com.jmex.model.converters.maxutils.TDSFile.<init>(TDSFile.java:92)

at com.jmex.model.converters.MaxToJme.convert(MaxToJme.java:75)

at com.jmex.model.converters.FormatConverter.attemptFileConvert(FormatConverter.java:87)

at com.jmex.model.converters.MaxToJme.main(MaxToJme.java:64)



As far as I can tell, the DisplaySystem.system is null and is created the first time is is requested in MaterialBlock.java ln 80.

myMatState=DisplaySystem.getDisplaySystem().getRenderer().createMaterialState();


This system's displaySystem is also create at this point with a null renderer.

The DummyDisplaySystem is instantiated in the same manner it was in jME 1, but this doesn't seem to work for jME 2.

Thoughts?

Ok, I figured it out.  The problem is with the way the DummyDisplaySystem is created.  It needs to be created as the DisplaySystem.system which means you need to do this:


DisplaySystem.getDisplaySystem("dummy");



Instead of

new DummyDisplaySystem();



I've made the change to my version of the model conversion code and it works.  Maybe getDisplaySystem(String) should be renamed to indicate exactly what it is doing.  It took me way to long to figure this out and it was in front of me the entire time.

As you already provided a working fix, i moved this topic from troubleshooting here to contribution depot :slight_smile:

Do you want to commit it yourself or should someone else check it in for you?



btw. Issues for jme 2 should be reported here:

http://code.google.com/p/jmonkeyengine/issues/list

I have no authorization to commit.  Here's a patch.



Cheers



PS.  Its been renamed to .txt, but it is a svn patch file.

so you basically replaced all

new DummyDisplaySystem();

with

DisplaySystem.getDisplaySystem("dummy");





Did you see what changed from jme 1 to jme 2 and why it doesn't work anymore?

Yes sir.  it was a simple change.  The one in Standard game wasn't cause trouble in any of the tests, but it will if anyone decides to make a model converter using it.



As to the underlying cause, I did not investigate it.  I would assume it has something to do with the nature of how the System Providers work with the DisplaySystems and the static accessor in DisplaySystem that returns the current system which is only set up if someone calls the getDisplaySystem() method that takes a String parameter.  I'm not sure how jme 1 handled this.  It may be that it didn't use the DisplaySystem's static accessor during the model conversion or that somehow the current system was setup in the constructors of the individual DisplaySystems.  Which would be very weird because the system providers would not have been created at that point.



I'm afraid I cannot make this very clear.  Its kind of a confusing.  I'm on IRC if you want to talk more.  Just hope on and ping lefty2shoes.



Cheers

r 3901: MaxToJme still works


    public DummyDisplaySystem() {
        system = new DummySystemProvider(this);
        created = true;
        renderer = new DummyRenderer();
    }



r 3953: MaxToJme still works

    public DummyDisplaySystem() {
        setSystemProvider(new DummySystemProvider(this));
        created = true;
        renderer = new DummyRenderer();
    }



r3954 "Errant check in, causing tests not to function."
now we get the NPE in MaxToJme

    public DummyDisplaySystem() {
        created = true;
        renderer = new DummyRenderer();
    }




so if we add this setSystemProvider() again in the DummydisplaySystem constructor, MaxToJme works again, maybe renanse can tell why it was removed.


Index: src/com/jme/system/dummy/DummyDisplaySystem.java
===================================================================
--- src/com/jme/system/dummy/DummyDisplaySystem.java   (revision 4041)
+++ src/com/jme/system/dummy/DummyDisplaySystem.java   (working copy)
@@ -59,6 +59,7 @@
     private DummyRenderer renderer;
 
     public DummyDisplaySystem() {
+        setSystemProvider(new DummySystemProvider(this));
         created = true;
         renderer = new DummyRenderer();
     }

Well, at a glance, I can tell you one reason it might have been removed.  The constructor for DummyDisplaySystem is making a DummySystemProvider which can make a DummyDisplaySystem. 



public class DummySystemProvider implements SystemProvider {
...
    public DisplaySystem getDisplaySystem() {
        if (displaySystem == null) {
            displaySystem = new DummyDisplaySystem();
        }
        return displaySystem;
    }



Sounds fine if the only way you make the object is by calling new DummyDisplaySystem, but as soon as you rely on the DummySystemProvider to create it which makes perfect sense to me, then you end up with some weird behavior.

I don't know.  Probably best to ask Ren.

well if we have FactoryMethods we should use them, so replacing 'new DummyDisplaySystem' with getDisplaySystem('dummy') is the smarter idea i guess.



The other question is, should the constructors of LWJGLDisplaySystem and DummyDisplaySystem be changed from public to protected, to avoid such mistakes?

going to commit this but will change DummySystemProvider.DUMMY_SYSTEM_IDENTIFIER  also to public like the other SystemProvider.

this is the complete patch:


Index: src/com/jme/system/dummy/DummySystemProvider.java
===================================================================
--- src/com/jme/system/dummy/DummySystemProvider.java   (revision 4044)
+++ src/com/jme/system/dummy/DummySystemProvider.java   (working copy)
@@ -51,7 +51,7 @@
     /**
      * The DummySystemProvider identifier
      */
-    private static final String DUMMY_SYSTEM_IDENTIFIER = "dummy";
+    public static final String DUMMY_SYSTEM_IDENTIFIER = "dummy";
 
     /**
      * The timer hold by this SystemProvider.
Index: src/com/jmex/model/converters/AseToJme.java
===================================================================
--- src/com/jmex/model/converters/AseToJme.java   (revision 4044)
+++ src/com/jmex/model/converters/AseToJme.java   (working copy)
@@ -56,7 +56,7 @@
 import com.jme.scene.state.MaterialState;
 import com.jme.scene.state.TextureState;
 import com.jme.system.DisplaySystem;
-import com.jme.system.dummy.DummyDisplaySystem;
+import com.jme.system.dummy.DummySystemProvider;
 import com.jme.util.TextureKey;
 import com.jme.util.TextureManager;
 import com.jme.util.export.binary.BinaryExporter;
@@ -80,7 +80,7 @@
      * @param args The array of parameters
      */
     public static void main(String[] args){
-        new DummyDisplaySystem();
+       DisplaySystem.getDisplaySystem(DummySystemProvider.DUMMY_SYSTEM_IDENTIFIER);
         new AseToJme().attemptFileConvert(args);
     }
 
Index: src/com/jmex/model/converters/ObjToJme.java
===================================================================
--- src/com/jmex/model/converters/ObjToJme.java   (revision 4044)
+++ src/com/jmex/model/converters/ObjToJme.java   (working copy)
@@ -60,7 +60,7 @@
 import com.jme.scene.state.MaterialState;
 import com.jme.scene.state.TextureState;
 import com.jme.system.DisplaySystem;
-import com.jme.system.dummy.DummyDisplaySystem;
+import com.jme.system.dummy.DummySystemProvider;
 import com.jme.util.TextureKey;
 import com.jme.util.TextureManager;
 import com.jme.util.export.binary.BinaryExporter;
@@ -117,7 +117,7 @@
      *            The array of parameters
      */
     public static void main(String[] args) {
-        new DummyDisplaySystem();
+       DisplaySystem.getDisplaySystem(DummySystemProvider.DUMMY_SYSTEM_IDENTIFIER);
         new ObjToJme().attemptFileConvert(args);
     }
     
Index: src/com/jmex/model/converters/MaxToJme.java
===================================================================
--- src/com/jmex/model/converters/MaxToJme.java   (revision 4044)
+++ src/com/jmex/model/converters/MaxToJme.java   (working copy)
@@ -38,7 +38,8 @@
 
 import com.jme.animation.SpatialTransformer;
 import com.jme.scene.Node;
-import com.jme.system.dummy.DummyDisplaySystem;
+import com.jme.system.DisplaySystem;
+import com.jme.system.dummy.DummySystemProvider;
 import com.jme.util.LittleEndien;
 import com.jme.util.export.binary.BinaryExporter;
 import com.jmex.model.converters.maxutils.TDSFile;
@@ -60,7 +61,7 @@
      * @param args The array of parameters.  args="file1.3ds file2.jme" will convert file1.3ds to jme and save it to file2.jme.
      */
     public static void main(String[] args){
-        new DummyDisplaySystem();
+       DisplaySystem.getDisplaySystem(DummySystemProvider.DUMMY_SYSTEM_IDENTIFIER);
         new MaxToJme().attemptFileConvert(args);
     }
 
Index: src/com/jmex/model/converters/MilkToJme.java
===================================================================
--- src/com/jmex/model/converters/MilkToJme.java   (revision 4044)
+++ src/com/jmex/model/converters/MilkToJme.java   (working copy)
@@ -54,6 +54,7 @@
 import com.jme.system.DisplaySystem;
 import com.jme.system.JmeException;
 import com.jme.system.dummy.DummyDisplaySystem;
+import com.jme.system.dummy.DummySystemProvider;
 import com.jme.util.LittleEndien;
 import com.jme.util.TextureKey;
 import com.jme.util.TextureManager;
@@ -93,7 +94,7 @@
      * @param args The array of parameters
      */
     public static void main(String[] args){
-        new DummyDisplaySystem();
+       DisplaySystem.getDisplaySystem(DummySystemProvider.DUMMY_SYSTEM_IDENTIFIER);
         new MilkToJme().attemptFileConvert(args);
     }
 
Index: src/com/jmex/model/converters/Md3ToJme.java
===================================================================
--- src/com/jmex/model/converters/Md3ToJme.java   (revision 4044)
+++ src/com/jmex/model/converters/Md3ToJme.java   (working copy)
@@ -44,7 +44,8 @@
 import com.jme.scene.Node;
 import com.jme.scene.TexCoords;
 import com.jme.scene.TriMesh;
-import com.jme.system.dummy.DummyDisplaySystem;
+import com.jme.system.DisplaySystem;
+import com.jme.system.dummy.DummySystemProvider;
 import com.jme.util.BinaryFileReader;
 import com.jme.util.export.binary.BinaryExporter;
 import com.jme.util.geom.BufferUtils;
@@ -69,7 +70,7 @@
     private KeyframeController vkc;
 
     public static void main(String[] args) {
-        new DummyDisplaySystem();
+       DisplaySystem.getDisplaySystem(DummySystemProvider.DUMMY_SYSTEM_IDENTIFIER);
         new Md3ToJme().attemptFileConvert(args);
     }
 
Index: src/com/jmex/model/converters/Md2ToJme.java
===================================================================
--- src/com/jmex/model/converters/Md2ToJme.java   (revision 4044)
+++ src/com/jmex/model/converters/Md2ToJme.java   (working copy)
@@ -46,8 +46,9 @@
 import com.jme.scene.Node;
 import com.jme.scene.TexCoords;
 import com.jme.scene.TriMesh;
+import com.jme.system.DisplaySystem;
 import com.jme.system.JmeException;
-import com.jme.system.dummy.DummyDisplaySystem;
+import com.jme.system.dummy.DummySystemProvider;
 import com.jme.util.BinaryFileReader;
 import com.jme.util.export.binary.BinaryExporter;
 import com.jme.util.geom.BufferUtils;
@@ -73,7 +74,7 @@
      *            The array of parameters
      */
     public static void main(String[] args) {
-        new DummyDisplaySystem();
+       DisplaySystem.getDisplaySystem(DummySystemProvider.DUMMY_SYSTEM_IDENTIFIER);
         new Md2ToJme().attemptFileConvert(args);
     }
 
Index: src/com/jmex/game/StandardGame.java
===================================================================
--- src/com/jmex/game/StandardGame.java   (revision 4044)
+++ src/com/jmex/game/StandardGame.java   (working copy)
@@ -54,7 +54,7 @@
 import com.jme.system.DisplaySystem;
 import com.jme.system.GameSettings;
 import com.jme.system.PreferencesGameSettings;
-import com.jme.system.dummy.DummyDisplaySystem;
+import com.jme.system.dummy.DummySystemProvider;
 import com.jme.util.GameTaskQueue;
 import com.jme.util.GameTaskQueueManager;
 import com.jme.util.NanoTimer;
@@ -292,7 +292,7 @@
                 initSound();
             }
         } else {
-            display = new DummyDisplaySystem();
+           display = DisplaySystem.getDisplaySystem(DummySystemProvider.DUMMY_SYSTEM_IDENTIFIER);
         }
     }