Really strange problem

Hello everyone!
I’m still working at my game : http://sgamed.blogspot.ro

I’m trying to load from a XML file locations of some SpriteSheets.

Here is the code:


			xmlLoader.loadXML("res/xml/armorsXML.xml");
			xmlLoader.searchByTag("armor");
			for(int i = 0; i < xmlLoader.getNodeList().getLength(); i++) {
				Node nNode = xmlLoader.getNodeList().item(i);
				if(nNode.getNodeType() == Node.ELEMENT_NODE) {
					Element eElement = (Element) nNode;
					String armorType = xmlLoader.getTagValue("armortype", eElement);
					String aLoc;
					
					switch(armorType) {
					case "head": aLoc = xmlLoader.getTagValue("armorSheet", eElement);
								headSheet[i] = new SpriteSheet(aLoc, 32, 48); break;
					case "chest": aLoc = xmlLoader.getTagValue("armorSheet", eElement);
								chestSheet[i] = new SpriteSheet(aLoc, 32, 48); break;
					case "legs": aLoc = xmlLoader.getTagValue("armorSheet", eElement);
								legsSheet[i] = new SpriteSheet(aLoc, 32, 48); break;
					case "boots": aLoc = xmlLoader.getTagValue("armorSheet", eElement);
								bootsSheet[i] = new SpriteSheet(aLoc, 32, 48); break;
					case "hands": aLoc = xmlLoader.getTagValue("armorSheet", eElement);
								handsSheet[i] = new SpriteSheet(aLoc, 32, 48); break;
					}
				}
			}

And this is my XML:


<?xml version="1.0"?>
<armors>
	<armor>
		<id>0</id>
		<armortype>head</armortype>
		<name>Head</name>
		<armor>20</armor>
		<armorSheet>res/images/armor/head0.png</armorSheet>
	</armor>
	<armor>
		<id>1</id>
		<armortype>chest</armortype>
		<name>Chest</name>
		<armor>20</armor>
		<armorSheet>res/images/armor/chest0.png</armorSheet>
	</armor>
	<armor>
		<id>2</id>
		<armortype>legs</armortype>
		<name>Legs</name>
		<armor>20</armor>
		<armorSheet>res/images/armor/legs0.png</armorSheet>
	</armor>
	<armor>
		<id>3</id>
		<armortype>boots</armortype>
		<name>Boots</name>
		<armor>20</armor>
		<armorSheet>res/images/armor/boots0.png</armorSheet>
	</armor>
	<armor>
		<id>4</id>
		<armortype>hands</armortype>
		<name>Hands</name>
		<armor>20</armor>
		<armorSheet>res/images/armor/hands0.png</armorSheet>
	</armor>
</armors>

And this is the error i get:


Exception in thread "main" java.lang.NullPointerException
	at com.game.util.XMLLoader.getTagValue(XMLLoader.java:32) //Line 30 in posted code
	at com.game.util.ResourceLoader.loadImages(ResourceLoader.java:57) //Line 7 in posted code
	at com.game.ClientLauncher.initStatesList(ClientLauncher.java:42)
	at org.newdawn.slick.state.StateBasedGame.init(StateBasedGame.java:164)
	at org.newdawn.slick.AppGameContainer.setup(AppGameContainer.java:390)
	at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:314)
	at com.game.ClientLauncher.main(ClientLauncher.java:38)

Another thing i found is that if i try to print the “xmlLoader.getNodeList().getLength()”, i get 10, instead of 5.

Here is the code of my XMLLoader:


import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.File;

public class XMLLoader {
	private NodeList nodeList;
	private Document doc;

	public void loadXML(String location) {
		try {
			File fXmlFile = new File(location);
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			doc = dBuilder.parse(fXmlFile);
			doc.getDocumentElement().normalize();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void searchByTag(String tag) {
		nodeList = doc.getElementsByTagName(tag);
	}

	public String getTagValue(String sTag, Element eElement) {
		NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
		Node nValue = (Node) nlList.item(0);
		return nValue.getNodeValue();
	}

	public NodeList getNodeList() { return nodeList; }
}

Thanks in advance. :smiley:

Start a debugger to see exactly which object is null at the given line.
Thus, you can also examine the actual read xml structure at runtime.

I am using Slick2D and i really don’t know how to see the needed variable in that tree…

Just set a breakpoint at line 30 of your loader class and see which object is null.
Or set a general NullpointException-Breakpoint (possible in Eclipse for example), run, and wait until it stops.

You could put a try catch in the getNodeValue method, that encloses the code… If it fails print out the parameters that lead to to the problem…

Something like this:


public String getTagValue(String sTag, Element eElement) {
      try{
          NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
          Node nValue = (Node) nlList.item(0);
          return nValue.getNodeValue();
      }
     catch(Exception ex)
     {
        System.out.println(string.Format("getTagValue failed for sTag '%s'%s", sTag, eElement == null ? " (eElement is null)" : ""));
        ex.printStackTrace();
        throw ex;
     }
   }

I’m not sure if the code is valid, as I have no running eclipse here :wink:

I tried your solution, but it print:


getTagValue failed for sTag 'armortype'
java.lang.NullPointerException
	at com.game.util.XMLLoader.getTagValue(XMLLoader.java:33)
	at com.game.util.ResourceLoader.loadImages(ResourceLoader.java:56)
	at com.game.ClientLauncher.initStatesList(ClientLauncher.java:40)
	at org.newdawn.slick.state.StateBasedGame.init(StateBasedGame.java:164)
	at org.newdawn.slick.AppGameContainer.setup(AppGameContainer.java:390)
	at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:314)
	at com.game.ClientLauncher.main(ClientLauncher.java:36)

So, it doesn’t print that element is null… Any solution?

This means that the parameter you passed is not null… you could add some more checks:


...
NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
if(nlList == null) throw new Exception("nlList is null");
Node nValue = (Node) nlList.item(0);
if(nValue == null) throw new Exception("nValue is null");
return nValue.getNodeValue();
...

like this you can isolate the problem. You still have to find out why the object is null, but you should be able to find out which one it was.

[edit]
also this line could be problematic:


NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();

You access the item directly without checking if it is available… I don’t have eclipse ready here, but i think you should change that part into something like that


NodeList list = eElement.getElementsByTagName(sTag);
if(list.getLength() <= 0) throw new Exception("No node found");		    	  
NodeList nlList = list.item(0).getChildNodes();

[/edit]

Yeah, but the problem is that for another file, this works great.

This is wierd…

EDIT: This is the code for the other file:


xmlLoader.loadXML("res/xml/weaponsXML.xml");
			xmlLoader.searchByTag("weapon");
			for(int i = 0; i < xmlLoader.getNodeList().getLength(); i++) {
				Node nNode = xmlLoader.getNodeList().item(i);
				if(nNode.getNodeType() == Node.ELEMENT_NODE) {
					Element eElement = (Element) nNode;
					String wLoc = xmlLoader.getTagValue("weaponSheet", eElement);
					String aLoc = xmlLoader.getTagValue("attackSheet", eElement);
					weaponsSheet[i][0] = new SpriteSheet(wLoc, 48, 48);
					weaponsSheet[i][1] = new SpriteSheet(aLoc, 48, 48);
				}
			}

And this is the other file:


<?xml version="1.0"?>
<weapons>
	<weapon>
		<id>0</id>
		<name>Sword</name>
		<damage>20</damage>
		<weaponSheet>res/images/weapons/swordSheet.png</weaponSheet>
		<attackSheet>res/images/weapons/swordAttackSheet.png</attackSheet>
	</weapon>
</weapons>

The problem isn’t for weapons, it’s with the armor. The weapons work as they should.

Sorry, removed my post as I noticed its irelevance XD

Currently I can’t see whats causing the problem. You have to find out, which call to getTagValue causes to fail and than analyze that case… Do you work with eclipse? Then you can set a breakpoint, when you right click on the left hand side of the code window. When you start the programm with “Debug As” (or by pressin F11), the programm is started in debug mode.

Its best you set the break point in the loadImages method (looking at the call stack, it seems that that is the root method described in your first post) and then step over every call with F6. If you find the call that causes the problem, you can debug again and then step into that method by pressing F5 instead of F6. Then you should be able to check the variables…

Or improve error handling and validation (see edit in my last post).

OH MY GOD!
I solved the problem. :emo:
This was so noob level.

If you look in my armors XML, you can see that in my ARMOR ELEMENTS I made an ARMOR PROPRETY. This is why I was getting length = 10 instead of 5.
I can’t belive I lost so much time for this thing. Thanks to everyone. ;D

You’re welcome…

Ahaha… I should have spotted that one XD

Btw. ever thought of serializing and deserializing objects directly with a framework? It can save you alot of headaches… I’m using xstream, but you could be working also with another library like jaxb. When you set it up correctly you can generate human readable (and editable) xml, but do not have to care about the serialization itself.

I made a little example, how you could handle serialization automatically with xstream :wink: Basically you have a bit more code (you need to set aliases for classes, register classes in xstream etc.) but it is really worth the time, as you do not have fight against those manual serialization issues.

I use it in my project and all xml files consumed by my game are generated from the code… I have a model generator class, that (programmatically) creates all the game xml files. If I change something in the class it could break the model, so you have to fix that. When your model is changed, you can run the model generator and all game xml files are updated. Like this I don’t have to care about the version of the xml file, as it always should be the newest version, when generation has been done.

You can find xstream here ( http://xstream.codehaus.org/ ) and I can really encourage you to do the two minute tutorial…

Code and xml output of my example => http://pastebin.com/JKyxRG6F

Short explanation about the example: The main method is in the XSTest class… The main method first generates a model in code and then saves it to a file… In a second step, this file is loaded and deserialized by xstream and the items in the store are printed out. The console output from the test program is:


Generated xml 'c:\temp\items.xml':
[...]
Weapon (1): Short sword, type: swords, attack sheet: data/sprites/swordattack.png
Weapon (2): Bastard sword, type: swords, attack sheet: data/sprites/swordattack.png
Weapon (3): Long sword, type: swords, attack sheet: data/sprites/swordattack.png
Armor (4): Studded leather armor, type: Chest, armor value: 20

I don’t know… I’m a little constrained about using many external libraries… As i said before, i am also using Slick2D.
In my vision, using many libraries => occupying memory. If I’m wrong, please, tell me.

Yeah, I understand that and thats also something that concerns me. but serialization is key feature, that I use very strongly in my projects and I just don’t have time to reinvent the wheel, when there is a suitable, well tested solution ready to use… i checked the jars… xstream and xppp (xstream uses the xppp library) are around 550 kb.

but you could still use JAXB, which should be part of the java default library (i don’t know how this is really called… im quite new to java and still not used to the terminology)… you do not need any external libraries for jaxb…

A library is not automatically “lighter” just because it comes bundled with the JDK. JAXB uses Xalan, which is a big heavy DOM implementation, so going with it just because it comes bundled with the JDK is penny-wise pound-foolish.

Can anyone point me to something that explains what is the serialization? Because I’m in mist with this subject.

Thanks!

Sometimes there is the need to persist an object for later use (a save game would be a nice example). The process ,that takes the java object and creates a representation of it (may be xml ,pure bytes or even a custom text format) is called serialization. The opposite is, when you have a representation ,that should be loaded as object. This is called deserialization.

Basically ,what you do is deserializing by hand.

Ok, thank you! I should search on Google some good methods for serialization, right?

Yeah ,you are right. Sorry, I mixed up some things… I was thinking of the package size (the distributable game) and not of the memory usage of the library…