| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
| <html xmlns="http://www.w3.org/1999/xhtml"> |
| <head> |
| <!-- -*- xhtml -*- --> |
| <title>NetBeans Visual Database Explorer Tutorial for NetBeans Platform 6.5</title> |
| <link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css"> |
| <meta name="AUDIENCE" content="NBUSER"> |
| <meta name="TYPE" content="ARTICLE"> |
| <meta name="EXPIRES" content="N"> |
| <meta name="developer" content="geertjan.wielenga@sun.com"> |
| <meta name="indexed" content="y"> |
| <meta name="description" |
| content="A walk-through of the basic features of the Visual Library API."> |
| <!-- Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. --> |
| <!-- Use is subject to license terms.--> |
| </head> |
| <body> |
| <h1>NetBeans Visual Database Explorer Tutorial</h1> |
| |
| <p>In this tutorial, you will learn how to create a visual view on top of |
| the content of a database: |
| |
| <p><img border="1" src="../images/tutorials/db/65-db-3.png"/></p> |
| |
| <p><b>Contents</b> |
| |
| <img src="../images/articles/65/netbeans-stamp65.gif" class="stamp" width="114" height="114" alt="Content on this page applies to NetBeans IDE 6.5" title="Content on this page applies to NetBeans IDE 6.5"> </p> |
| <ul class="toc"> |
| <li><a href="#getting-started">Setting Up the Module</a> |
| <li><a href="#creating-the-action">Creating the Action</a> |
| <li><a href="#creating-the-window">Creating the Window</a> |
| <li><a href="#creating-the-scene">Creating the Scene</a> |
| <li><a href="#connect_database_to_scene">Connect the Database to the Scene</a> |
| </ul> |
| |
| <p><b>To follow this tutorial, you need the software and resources listed in the following |
| table.</b></p> |
| |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">NetBeans IDE</a></td> |
| <td class="tbltd1">version 6.5</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://java.sun.com/javase/downloads/index.jsp">Java Developer Kit (JDK)</a></td> |
| <td class="tbltd1">Version 6 or<br/>version 5</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p class="tips">Optionally, for troubleshooting purposes, you can <a href="http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=14287">download the |
| completed sample for NetBeans Platform 6.5</a> and inspect the sources. |
| |
| <p>All the information you need to know for working with the Visual Library API, |
| as well as with the Database Explorer API, is collected at the following locations: |
| |
| <ul> |
| <li><a href="http://graph.netbeans.org/">Visual Library Project Page</a> |
| <li><a href="http://graph.netbeans.org/documentation.html">Visual Library 2.0 - Documentation</a> |
| <li><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-api-visual/overview-summary.html">Visual Library API Javadoc</a> |
| <li><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-db/overview-summary.html">Database Explorer API Javadoc</a> |
| </ul> |
| |
| <p>Also, see <a href="http://www.javalobby.org/eps/netbeans_visual_library/">Roman Strobl's Visual Library |
| Screencast</a> on Javalobby. |
| |
| <p>Before continuing, you are assumed to have read |
| the <a href="https://platform.netbeans.org/tutorials/nbm-visual_library.html">NetBeans Visual Library Tutorial</a>, which gives you the basics for |
| working with the Visual Library. The basics discussed |
| in that tutorial will not be repeated here. |
| |
| <!-- ===================================================================================== --> |
| |
| <p><h2><a name="getting-started"></a>Setting Up the Module</h2> |
| |
| <p>In this section, we use wizards to create a module project and |
| a custom window component. |
| |
| <ol> |
| <li>Choose File > New Project (Ctrl+Shift+N). Under Categories, select NetBeans Modules. |
| Under Projects, select Module. Click Next.</li> |
| <li>In the Name and Location panel, type <tt>DatabaseExplorerDemo</tt> in the Project Name field. |
| Change the Project Location to any directory on your computer. Leave the Standalone Module option |
| and Set as Main Project checkbox selected. Click Next.</li> |
| <li>In the Basic Module Configuration panel, type <tt>org.demo</tt> |
| in Code Name Base. |
| <li><p>Select "Generate XML Layer". Leave the |
| locations of both the localizing bundle and the XML layer file |
| so that they will be stored in a package with |
| the name <tt>org/demo</tt>. Click Finish.</p> |
| |
| <p>The IDE creates the <tt>DatabaseExplorerDemo</tt> project. The project contains all of your sources and project |
| metadata, such as the project's Ant build script. The project opens in the IDE. You can view its logical |
| structure in the Projects window (Ctrl+1) and its file structure in the Files window (Ctrl+2). |
| </li> |
| |
| <p><li>Right-click the project, choose Properties, click Libraries |
| in the Project Properties dialog box and declare a dependency on the following APIs: |
| |
| <p><ul> |
| <li>Database Explorer |
| <li>Nodes API |
| <li>Swing Layout Extensions Integration |
| <li>UI Utilities API |
| <li>Utilities API |
| <li>Visual Library API |
| <li>Window System API |
| </ul> |
| |
| <p><strong class="notes">Note: </strong> In 6.5, you need to set an implementation |
| dependency on the Database Explorer API. Do so by selecting the Database Explorer |
| item in the Libraries panel of the Project Properties dialog, clicking Edit, |
| and then clicking 'Implementation Version'. By doing this, you are setting |
| a dependency on internal classes that will change in future releases. Currently |
| there is no other way of completing the scenario in this tutorial than to set |
| an implementation dependency. In 7.0, a different approach will be taken and |
| an implementation dependency will not be needed. |
| |
| <p><li>Click OK to close the Project Properties dialog. |
| |
| </ol> |
| |
| <p><h2><a name="creating-the-action"></a>Creating the Action</h2> |
| |
| <p>We will create an action that will only be enabled |
| if the activated node has the <tt>ConnectionNode</tt> from |
| the Database Explorer API in its Lookup. |
| |
| <ol> |
| |
| <li><p>Right-click the module project, choose |
| New > Other and choose Action from the |
| Module Development category:</p> |
| |
| <p><img src="../images/tutorials/db/65-db-1.png"/></p> |
| |
| <p>Click Next. |
| |
| <p><li>Select 'Conditionally Enabled (use CookieAction)' |
| and specify the following class as the capability |
| that needs to be available for the menu item to |
| be enabled:</p> |
| |
| <pre>org.netbeans.modules.db.explorer.nodes.ConnectionNode</pre> |
| |
| <p>You should see the following:</p> |
| |
| <p><img src="../images/tutorials/db/65-db-2.png"/></p> |
| |
| <p>Click Next. |
| |
| <p><li>In the GUI Registration page, accept all the defaults. Click Next. |
| |
| <p><li><p>Type "ShowDatabaseStructureAction" as the class name and then type |
| "Show Database Structure" as the display name. Optionally, select an |
| icon (16x16 pixels in size). Click Finish. |
| |
| <p><li>In the editor, you will see a red error underline for the <tt>ConnectionNode</tt> |
| class. Click the lightbulb in the left side of the editor to let the IDE |
| add the import statement to the import declaration at the top of the class. |
| |
| </ol> |
| |
| <p>You now have a new <tt>CookieAction</tt> class that will be displayed |
| in the main menu bar. However, it will only be enabled if the <tt>ConnectionNode</tt> |
| class is available in the current Lookup. |
| |
| <p><h2><a name="creating-the-window"></a>Creating the Window</h2> |
| |
| <p>In this section, we create a new window component that |
| will hold our scene. |
| |
| <ol> |
| |
| <li>Right-click the module project, choose |
| New > Other and choose Window Component from the |
| Module Development category. Click Next. Choose <tt>editor</tt> |
| in the drop-down list. Do not select Open on Application Start. Click Next. |
| |
| <p><li>Type <tt>Demo</tt> in Class Name Prefix. Optionally, |
| add an icon with a dimension of 16x16 pixels. Click Finish.</p> |
| |
| <p>Multiple files are generated, one of them is <tt>DemoTopComponent</tt>. |
| Open this file in Design mode. |
| |
| <p><li>Right-click in the TopComponent in Design mode, choose Set Layout, |
| and select BorderLayout. |
| |
| <p><li>Switch to Source mode and change the <tt>getPersistenceType</tt> method |
| to return <tt>TopComponent.PERSISTENCE_NEVER</tt>. |
| |
| </ol> |
| |
| <p><h2><a name="creating-the-scene"></a>Creating the Scene</h2> |
| |
| <p>Programming with the Visual Library API is similar to programming in Swing. You build |
| and modify a tree of visual elements that are called "widgets". The root of the tree is |
| represented by a Scene class which holds all the visual data of the scene. The scene is a widget. |
| You have to create a scene view, which is a JComponent. You must then add |
| the JComponent to a JScrollPane. |
| |
| <p>In this section, |
| we add a JScrollPane to our TopComponent. Then we create a new |
| Visual Library scene in a separate Java source file. Next, we pass the |
| scene to the TopComponent, so that it can be displayed in |
| the TopComponent's JScrollPane. We then install the module project and display |
| our first scene.</p> |
| |
| <ol> |
| |
| <li>Use the Palette (Ctrl-Shift-8) to drop a |
| <tt>JScrollPane</tt> on the TopComponent. |
| |
| <p><li>In the <tt>org.demo</tt> package, create a Java class called <tt>DBGraphScene</tt>. |
| Let the class extend <tt>VMDGraphScene</tt>.</p> |
| |
| <p>A red error underline and a lightbulb appears. Let the IDE generate the import statement. |
| |
| <p>A red error underline and a lightbulb appears again. Let the IDE generate the class's abstract methods. |
| |
| <p><li>Replace the content of the class with the following: |
| |
| <pre class="examplecode">import java.awt.Image; |
| import java.awt.Point; |
| import java.util.Arrays; |
| import java.util.List; |
| import org.netbeans.api.visual.vmd.VMDGraphScene; |
| import org.netbeans.api.visual.vmd.VMDNodeWidget; |
| import org.netbeans.api.visual.vmd.VMDPinWidget; |
| import org.openide.util.ImageUtilities; |
| |
| public class DBGraphScene extends VMDGraphScene{ |
| |
| private static final Image IMAGE_LIST = ImageUtilities.loadImage("org/demo/resources/list_16.png"); // NOI18N |
| private static final Image IMAGE_CANVAS = ImageUtilities.loadImage("org/demo/resources/custom_displayable_16.png"); // NOI18N |
| private static final Image IMAGE_COMMAND = ImageUtilities.loadImage("org/demo/resources/command_16.png"); // NOI18N |
| private static final Image IMAGE_ITEM = ImageUtilities.loadImage("org/demo/resources/item_16.png"); // NOI18N |
| private static final Image GLYPH_PRE_CODE = ImageUtilities.loadImage("org/demo/resources/preCodeGlyph.png"); // NOI18N |
| private static final Image GLYPH_POST_CODE = ImageUtilities.loadImage("org/demo/resources/postCodeGlyph.png"); // NOI18N |
| private static final Image GLYPH_CANCEL = ImageUtilities.loadImage("org/demo/resources/cancelGlyph.png"); // NOI18N |
| private static int nodeID = 1; |
| private static int edgeID = 1; |
| |
| public DBGraphScene() { |
| String mobile = createNode (this, 100, 100, IMAGE_LIST, "menu", "List", null); |
| createPin (this, mobile, "start", IMAGE_ITEM, "Start", "Element"); |
| String game = createNode (this, 600, 100, IMAGE_CANVAS, "gameCanvas", "MyCanvas", Arrays.asList (GLYPH_PRE_CODE, GLYPH_CANCEL, GLYPH_POST_CODE)); |
| createPin (this, game, "ok", IMAGE_COMMAND, "okCommand1", "Command"); |
| createEdge (this, "start", game); |
| createEdge (this, "ok", mobile); |
| } |
| |
| private static String createNode (VMDGraphScene scene, int x, int y, Image image, String name, String type, List<Image> glyphs) { |
| String nodeID = "node" + DBGraphScene.nodeID ++; |
| VMDNodeWidget widget = (VMDNodeWidget) scene.addNode (nodeID); |
| widget.setPreferredLocation (new Point (x, y)); |
| widget.setNodeProperties (image, name, type, glyphs); |
| scene.addPin (nodeID, nodeID + VMDGraphScene.PIN_ID_DEFAULT_SUFFIX); |
| return nodeID; |
| } |
| |
| |
| private static void createPin (VMDGraphScene scene, String nodeID, String pinID, Image image, String name, String type) { |
| ((VMDPinWidget) scene.addPin (nodeID, pinID)).setProperties (name, null); |
| } |
| |
| |
| private static void createEdge (VMDGraphScene scene, String sourcePinID, String targetNodeID) { |
| String edgeID = "edge" + DBGraphScene.edgeID ++; |
| scene.addEdge (edgeID); |
| scene.setEdgeSource (edgeID, sourcePinID); |
| scene.setEdgeTarget (edgeID, targetNodeID + VMDGraphScene.PIN_ID_DEFAULT_SUFFIX); |
| } |
| |
| }</pre> |
| |
| <p><li>Add an instance variable for the scene to the top of the TopComponent's source code: |
| |
| <pre lass="examplecode">private DBGraphScene scene = new DBGraphScene();</pre> |
| |
| <p>Add the scene to the JScrollPane's ViewportView, at the end of the TopComponent's |
| constructor: |
| |
| <pre lass="examplecode">jScrollPane1.setViewportView( scene.createView() );</pre> |
| |
| <p><li><p>Right-click the module and choose Run. Open the Services window (Ctrl-5), |
| right-click one of the database connection nodes, and then select "Demo" from |
| the Window menu. The window component should open and show you |
| the following:</p> |
| |
| <p><img src="../images/tutorials/db/65-db-4.png"/></p> |
| |
| </ol> |
| |
| <!-- ===================================================================================== --> |
| <p><h2><a name="connect_database_to_scene"></a>Connect the Database to the Scene</h2> |
| |
| <p>In this section, we connect to a selected database by using the Database Explorer API. |
| We then pass the connection to the scene. In the scene, we parse the connection, |
| extract the data, and visually display the data in the scene. |
| |
| <ol> |
| |
| <li>In your action class, you need to make a connection to a selected |
| database and pass it to your window: |
| |
| <pre class="examplecode">@Override |
| protected void performAction(Node[] activatedNodes) { |
| ConnectionNode connectionNode = activatedNodes[0].getLookup().lookup(ConnectionNode.class); |
| DatabaseConnection databaseConnection = connectionNode.getInfo().getDatabaseConnection().getDatabaseConnection(); |
| if (databaseConnection.getJDBCConnection() == null) { |
| ConnectionManager.getDefault().showConnectionDialog(databaseConnection); |
| } |
| Connection connection = databaseConnection.getJDBCConnection(); |
| DemoTopComponent win = DemoTopComponent.findInstance(); |
| win.open(); |
| win.requestActive(); |
| win.setConnection(connection); |
| }</pre> |
| |
| <p>A red error underline will appear below the last line, because it refers |
| to a statement that we have not defined yet. We will do so in the next step. |
| |
| <p><li>Back in your window component, you need to receive the connection and |
| call the scene, as shown below: |
| |
| <pre class="examplecode">final class DemoTopComponent extends TopComponent { |
| |
| private static DemoTopComponent instance; |
| |
| private static final String PREFERRED_ID = "DemoTopComponent"; |
| |
| private DBGraphScene scene; |
| |
| private DemoTopComponent() { |
| initComponents(); |
| setName(NbBundle.getMessage(DemoTopComponent.class, "CTL_DemoTopComponent")); |
| setToolTipText(NbBundle.getMessage(DemoTopComponent.class, "HINT_DemoTopComponent")); |
| } |
| |
| public void setConnection(Connection connection){ |
| scene = new DBGraphScene(connection); |
| jScrollPane1.setViewportView( scene.createView() ); |
| } |
| |
| ... |
| ... |
| ... |
| </pre> |
| |
| <p>In the scene, the constructor that receives the connection does not |
| exist. We will create it in the next step. Until then, reference to |
| that constructor, above, is underlined in red. |
| |
| <li>In the <tt>DBGraphScene</tt> class, extend the code as follows: |
| |
| <pre class="examplecode">public class DBGraphScene extends VMDGraphScene { |
| |
| private static final Image IMAGE_LIST = ImageUtilities.loadImage("org/demo/resources/list_16.png"); // NOI18N |
| private static final Image IMAGE_ITEM = ImageUtilities.loadImage("org/demo/resources/item_16.png"); // NOI18N |
| |
| private static int edgeID = 1; |
| |
| public DBGraphScene(Connection connection) { |
| try { |
| createSceneFromConnection(connection); |
| } catch (SQLException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| private void createSceneFromConnection(Connection jdbcConnection) throws SQLException { |
| ArrayList<String> tables = new ArrayList<String>(); |
| DatabaseMetaData databaseMetaData = jdbcConnection.getMetaData(); |
| String[] names = {"TABLE"}; |
| ResultSet resultSet = databaseMetaData.getTables(null, "%", "%", names); |
| while (resultSet.next()) { |
| String table = resultSet.getString("TABLE_NAME"); |
| tables.add(table); |
| createNode(this, (int) (Math.random() * 800), (int) (Math.random() * 800), IMAGE_LIST, table, "Table", null); |
| ResultSet columns = jdbcConnection.getMetaData().getColumns(null, null, table.toUpperCase(), "%"); |
| while (columns.next()) { |
| String columnName = columns.getString("COLUMN_NAME"); |
| createPin(this, table, table + ":" + columnName, IMAGE_ITEM, columnName, columnName); |
| } |
| } |
| for (String string : tables) { |
| ResultSet resultSet1 = databaseMetaData.getExportedKeys(null, null, string); |
| while (resultSet1.next()) { |
| String pkTable = resultSet1.getString("PKTABLE_NAME"); |
| String pkColumn = resultSet1.getString("PKCOLUMN_NAME"); |
| String fkTable = resultSet1.getString("FKTABLE_NAME"); |
| String fkColumn = resultSet1.getString("FKCOLUMN_NAME"); |
| createEdge(this, fkTable + ":" + fkColumn, pkTable + ":" + pkColumn); |
| } |
| } |
| this.moveTo(null); |
| } |
| |
| private static String createNode(VMDGraphScene scene, int x, int y, Image image, String name, String type, java.util.List<Image> glyphs) { |
| String node = name; |
| VMDNodeWidget widget = (VMDNodeWidget) scene.addNode(node); |
| widget.setPreferredLocation(new Point(x, y)); |
| widget.setNodeProperties(image, name, type, glyphs); |
| return node; |
| } |
| |
| private static void createPin(VMDGraphScene scene, String nodeID, String pinID, Image image, String name, String type) { |
| ((VMDPinWidget) scene.addPin(nodeID, pinID)).setProperties(name, null); |
| } |
| |
| private static void createEdge(VMDGraphScene scene, String sourcePinID, String targetPinID) { |
| String edge = "edge" + DBGraphScene.edgeID++; |
| scene.addEdge(edge); |
| scene.setEdgeSource(edge, sourcePinID); |
| scene.setEdgeTarget(edge, targetPinID); |
| } |
| |
| private void moveTo(Point point) { |
| int index = 0; |
| for (String node : getNodes()) { |
| getSceneAnimator().animatePreferredLocation(findWidget(node), point != null ? point : new Point(++index * 100, index * 100)); |
| } |
| } |
| |
| } |
| </pre> |
| |
| |
| <p>The <tt>createSceneFromConnection</tt> method gets the |
| <tt>DatabaseMetadata ( jdbcConnection.getMetaData() )</tt> from the <tt>Connection</tt>. |
| With the subsequent calls to <tt>getTables</tt>, the table structure is retrieved and |
| the nodes of the graph are created. For every table, <tt>getColumns</tt> is called and |
| a Pin is added for every column to the table node. These pins can be used in |
| a subsequent step to create a connection between two tables. Now we |
| iterate through the tables and call <tt>getExportedKeys</tt> to get hold of |
| the <tt>ForeignKeys</tt>. For every exported key, an edge is created between the |
| pins of the related columns. The <tt>moveTo</tt> method does the animation |
| when the window is opened. |
| |
| <p><li><p>Run the module again. Open the Services window. Expand the Databases |
| node. Select one of the connection nodes. The "Show Database Structure" menu |
| item, under the File menu, |
| should now be enabled. Select it and now your scene should open |
| and look as follows:</p> |
| |
| <p><img border="1" src="../images/tutorials/db/65-db-3.png"/></p> |
| |
| </ol> |
| |
| <!-- ===================================================================================== --> |
| |
| <p>Congratulations, you have completed a Visual Library scene that connects to a database |
| and visually displays its content.</p> |
| |
| <br> |
| <div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback:%20Visual%20Database%20Explorer%20API%20Tutorial%20NetBeans">Send Us Your Feedback</a></div> |
| <br style="clear:both;" /> |
| |
| |
| <a name="next_steps"></a><h2>Next Steps</h2> |
| <p>For more information |
| on working with the Visual Library API, see:</p> |
| |
| <ul> |
| <li><a href="http://www.javalobby.org/eps/netbeans_visual_library/">Roman Strobl's Visual Library |
| Screencast</a> on Javalobby. |
| <li><a href="http://graph.netbeans.org/">Visual Library Project Page</a> |
| <li><a href="http://graph.netbeans.org/documentation.html">Visual Library 2.0 - Documentation</a> |
| <li><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-api-visual/overview-summary.html">Visual Library API Javadoc</a> |
| <li><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-db/overview-summary.html">Database Explorer API Javadoc</a> |
| </ul> |
| |
| <p>With thanks to Toni Epple, who wrote the first version |
| of this tutorial, <a href="http://wiki.netbeans.org/VisualDatabaseExplorer">A Visual Database Explorer for NetBeans</a>. |
| |
| </body> |
| |
| </html> |