0

Im building simple family tree application and using Jung to draw the chart. So far I am able to draw and save the chart into embedded database using sqlitejdbc from zentus. I've yet create the function to clear the canvas though, so I have to restart the application to test the opening the database. But when I want to load them back, the application just froze and I encountered this error.

  path:C:\Users\PaLi\Desktop\psm things\chart4.db
    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at FamTree.vertexPainter.transform(vertexPainter.java:20)
at FamTree.vertexPainter.transform(vertexPainter.java:1)
at edu.uci.ics.jung.visualization.renderers.BasicVertexRenderer.paintShapeForVertex(BasicVertexRenderer.java:98)
at edu.uci.ics.jung.visualization.renderers.BasicVertexRenderer.paintIconForVertex(BasicVertexRenderer.java:74)
at edu.uci.ics.jung.visualization.renderers.BasicVertexRenderer.paintVertex(BasicVertexRenderer.java:37)
at edu.uci.ics.jung.visualization.renderers.BasicRenderer.renderVertex(BasicRenderer.java:70)
at edu.uci.ics.jung.visualization.renderers.BasicRenderer.render(BasicRenderer.java:55)
at edu.uci.ics.jung.visualization.BasicVisualizationServer.renderGraph(BasicVisualizationServer.java:367)
 at edu.uci.ics.jung.visualization.BasicVisualizationServer.paintComponent(BasicVisualizationServer.java:321)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5221)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1482)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1413)
at javax.swing.RepaintManager.paint(RepaintManager.java:1206)
at javax.swing.JComponent._paintImmediately(JComponent.java:5169)
at javax.swing.JComponent.paintImmediately(JComponent.java:4980)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:770)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:728)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:677)
at javax.swing.RepaintManager.access$700(RepaintManager.java:59)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1621)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:705)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:675)
at    java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at    java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

This is the vertex painter transformer's code. It works perfectly fine if its not loading the database part.

package FamTree;

import org.apache.commons.collections15.Transformer;

import java.awt.*;
import java.util.Map;

class vertexPainter implements Transformer<Integer, Paint>
{
private Map<Integer,Person> tempV;

public vertexPainter(Map<Integer,Person> passV)
{
    tempV = passV;
}
public Paint transform(Integer v) 
{

    if (tempV.get(v).getpSex().equalsIgnoreCase("male")) 
        return (Color.blue); 
    else
    return (Color.red);

}
}

This is the initialization of graph and setting up the vv.

     public TCanvas(){

     graph = new SparseMultigraph<Integer,Number>();

     layout2 = new StaticLayout<Integer,Number>(graph,new Dimension(2000,2000));

     vv =  new VisualizationViewer<Integer,Number>(layout2);
     vv.setBackground(Color.white);
     vv.setVertexToolTipTransformer(new ToStringLabeller<Integer>());
     vv.getRenderContext().setVertexFillPaintTransformer(new vertexPainter(vertex));
vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.S);
     vv.getRenderContext().setVertexLabelTransformer(new vertexLabel(vertex));
     vv.getRenderContext().setEdgeDrawPaintTransformer(new edgePainter());

     Transformer<Number,String> stringer = new Transformer<Number,String>(){
         public String transform(Number e) {
             return "Edge:"+e+ "-"+graph.getEndpoints(e).toString();
         }
     };

     vv.getRenderContext().setEdgeLabelTransformer(stringer);

     EdgeLabelRenderer edgeLabelRenderer= vv.getRenderContext().getEdgeLabelRenderer();
     edgeLabelRenderer.setRotateEdgeLabels(false);



     gm = new DefaultModalGraphMouse<Integer, Number>();
     vv.setGraphMouse(gm);
     gm.add(new PopupGraphMousePlugin());

     GraphZoomScrollPane scrollPane2 = new GraphZoomScrollPane(vv);

     JPanel vvPanel = new JPanel();
     vvPanel.setLayout(new BorderLayout());
     vvPanel.add(scrollPane2);

     addBottomControls(vvPanel);

     Container content = getContentPane();
     content.add(vvPanel);  
     }//TCanvas()

This is the part to load the database.

     menu.add(new AbstractAction("Open") {
        public void actionPerformed(ActionEvent e) {

            JFileChooser open  = new JFileChooser();
            final File file ;

            int vat = open.showOpenDialog(rootPane);

            if(vat==JFileChooser.APPROVE_OPTION){

                file = open.getSelectedFile();

                String fPath = file.getAbsolutePath();

                System.out.println("path:"+fPath);
                try{

                    Class.forName("org.sqlite.JDBC");
                    Connection conn = DriverManager.getConnection("jdbc:sqlite:"+fPath);

                     Statement stat = conn.createStatement();

                     ResultSet rs = stat.executeQuery("select * from Person;");
                     while (rs.next()) {


                        Integer pid = rs.getInt("pID");
                        String pname = rs.getString("pName");
                        String psex = rs.getString("pSex");
                        Integer fatherid = (Integer)rs.getInt("fatherID");
                        Integer motherid = (Integer)rs.getInt("motherID");
                        Integer spouseid = (Integer)rs.getInt("spouseID");

                        Person personInfo = new Person();

                        personInfo.setpID(pid);
                        personInfo.setpName(pname);
                        personInfo.setpSex(psex);
                        personInfo.setFatherID(fatherid);
                        personInfo.setMotherID(motherid);
                        personInfo.setSpouseID(spouseid);

                        vertex.put(pid,personInfo);
                        graph.addVertex(pid);
                        vv.repaint();

                        ResultSet rs2 = stat.executeQuery("select * from Location;");
                         while (rs2.next()) {

                             if(rs2.getInt("pID")==pid){

                                 Point2D.Double loc = new Point2D.Double();

                                 Double x = rs2.getDouble("pointX");
                                 Double y = rs2.getDouble("pointY");
                                 loc.setLocation(x, y);

                                 layout2.setLocation(pid, vv.getRenderContext().getMultiLayerTransformer().inverseTransform(loc));
                                 vv.repaint();
                             }
                         }
                         rs2.close();


                     }
                     rs.close();

                    ResultSet rs3 = stat.executeQuery("select * from Relation;");

                    while (rs3.next()) {

                         Point2D.Double loc2 = new Point2D.Double();

                         Number edgeid = (Number)rs3.getInt("edgeID");
                         Integer v1 = rs3.getInt("vertex1");
                         Integer v2 = rs3.getInt("vertex2");
                         String type = rs3.getString("RelationType");

                         Relation relation = new Relation(edgeid, v1, v2, type);
                         edge.put(edgeid, relation);
                         if(type.equalsIgnoreCase("DIRECTED")){
                             graph.addEdge(edgeid, v1, v2, EdgeType.DIRECTED);
                         }
                         if(type.equalsIgnoreCase("UNDIRECTED")){
                             graph.addEdge(edgeid, v1, v2, EdgeType.UNDIRECTED);
                         }
                        vv.repaint();


                    }
                    rs3.close();

                    conn.close();
                    vv.repaint();

                }
                catch (Exception ex) {
                    // TODO: handle exception
                    ex.printStackTrace();
                }

            }

        }});

I really dont know whats happening here as Im pretty sure the opening and retrieving database part have no problem.

Fadhlie Ikram
  • 119
  • 2
  • 14

1 Answers1

1

In vertexPainter#transform, either the map is null or it has no value for the integer key ("v") or the value pSex property for one record is null (maybe not set on the database table).

A debugger could tell you exactly what's the actual problem.


In the TCanvas constructor, I see this line of code:

vv.getRenderContext().setVertexFillPaintTransformer(new vertexPainter(vertex));

That's where you create the painter with a map, but I don't see a declaration and initialization of that map. So there's a good chance, that you pass an empty map to the painter and thus the painter can't find a value for a key (because the map is empty). This would definitly lead to an NPE.


It's not about studying the error log. In eclipse:

  1. switch to the debug perpsective
  2. find the "Breakpoints" view (usually a tab in the upper right corner)
  3. on that view there's a button with a "J" and an exclamation mark, the tool tip says "Add Java Exception Breakpoint"
  4. Click on that button and type NPE, then select the NullPointerException
  5. Now you have a breakpoint that will halt on every null pointer exception
  6. Debug your application (like "Run")
  7. Eventually the application will halt and you'll see a stacktrace in the Debug view. One frame it your vertexPainter, select that row and it'll take you to the line of code that threw the NPE. Now you have to look at the variable values and play with the inspect function.
Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • I cant find the problem. It works fine when I start the application and draw the graph from nothing. So from my understanding, the mechanism of drawing the vertex and edges load from the database should be the same. – Fadhlie Ikram Aug 12 '12 at 14:11
  • 1
    Debug. Hope you use an ide: set a breakpoint to halt on NullPointerExceptions and inspect the variables. One of those that I pointed out is `null`. – Andreas Dolk Aug 12 '12 at 14:14
  • Im using eclipse indigo ide. And I dont understand what are do you want me to do. How do I do the halt NullPointerExceptions? Sorry Im really dont know how to debug using the error log. – Fadhlie Ikram Aug 12 '12 at 14:20
  • I've run the inspection and the debugger stop to this line: vv.getRenderContext().setVertexFillPaintTransformer(new vertexPainter(vertex)); But I still dont get it. It work perfectly fine when i draw the chart from scratch. – Fadhlie Ikram Aug 12 '12 at 15:01
  • 1
    Maybe the render context is null. comment that line and debug again, will it stop with a NPE on the next line? – Andreas Dolk Aug 12 '12 at 15:16
  • So i changed the code. vp = new vertexPainter(vertex); vv.getRenderContext().setVertexFillPaintTransformer(vp); I ran the debug. I set the breakpoint to stop at NPE only, unchecked the other option in break point 'tab'. It ran well, no stopping this time. The application manage to show. But when I tried to open the databse I got this; http://i128.photobucket.com/albums/p199/paliey87/debug.jpg the 1 over the console is the counter that I set when retrieving the data. This means it only loop once. What could be the problem? – Fadhlie Ikram Aug 12 '12 at 15:49
  • Don't care about that exception - eclipse will halt on catched exceptions too. It happens quite often that you catch expected exceptions in drivers and frameworks. – Andreas Dolk Aug 12 '12 at 16:06
  • I solved the problem. It turns out its the sqlite problem, or rather the way I retrieve the data back. I cut and replace the r2 loop out of r1 loop, and now it can load back the chart! Thanks for lending me your time, and teach me step by step on how to debug and trace the problem. Your help is much appreciated sir! – Fadhlie Ikram Aug 12 '12 at 16:23