Geertjan is a DZone Zone Leader and has posted 468 posts at DZone. You can read more from them at their website. View Full User Profile

How to Create a Swing CRUD Application on NetBeans Platform 6.8

12.08.2009
| 148050 views |
  • submit to reddit

Create

In this section, you allow the user to create a new entry in the database.

  1. Right-click the CustomerEditor module and choose "New Action". Use the New Action wizard to create a new "Always Enabled" action. The new action should be displayed anywhere in the toolbar and/or anywhere in the menu bar. In the next step of the wizard, call the action NewAction.

    Note: Make sure that you have a 16x16 icon available, which the wizard forces you to select if you indicate that you want the action to be invoked from the toolbar.

  2. In the New action, let the TopComponent be opened, together with emptied JTextFields:
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;

    public final class NewAction implements ActionListener {

    public void actionPerformed(ActionEvent e) {
    EditorTopComponent tc = EditorTopComponent.getDefault();
    tc.resetFields();
    tc.open();
    tc.requestActive();
    }

    }

    Note: The action implements the ActionListener class, which is bound to the application via entries in the layer file, put there by the New Action wizard. Imagine how easy it will be when you port your existing Swing application to the NetBeans Platform, since you'll simply be able to use the same Action classes that you used in your original application, without needing to rewrite them to conform to Action classes provided by the NetBeans Platform!

  3. In the EditorTopComponent, add the following method for resetting the JTextFields and creating a new Customer object:

    public void resetFields() {
    customer = new Customer();
    jTextField1.setText("");
    jTextField2.setText("");
    }
  4. In the SaveCookie, ensure that a return of null indicates that a new entry is saved, instead of an existing entry being updated:
    public void save() throws IOException {

    Confirmation message = new NotifyDescriptor.Confirmation("Do you want to save \""
    + jTextField1.getText() + " (" + jTextField2.getText() + ")\"?",
    NotifyDescriptor.OK_CANCEL_OPTION,
    NotifyDescriptor.QUESTION_MESSAGE);

    Object result = DialogDisplayer.getDefault().notify(msg);

    //When user clicks "Yes", indicating they really want to save,
    //we need to disable the Save button and Save menu item,
    //so that it will only be usable when the next change is made
    //to the text field:
    if (NotifyDescriptor.YES_OPTION.equals(result)) {
    fire(false);
    EntityManager entityManager = Persistence.createEntityManagerFactory("CustomerLibraryPU").createEntityManager();
    entityManager.getTransaction().begin();
    if (customer.getCustomerId() != null) {
    Customer c = entityManager.find(Customer.class, cude.getCustomerId());
    c.setName(jTextField1.getText());
    c.setCity(jTextField2.getText());
    entityManager.getTransaction().commit();
    } else {
    Query query = entityManager.createQuery("SELECT c FROM Customer c");
    List<Customer> resultList = query.getResultList();
    customer.setCustomerId(resultList.size()+1);
    customer.setName(jTextField1.getText());
    customer.setCity(jTextField2.getText());
    //add more fields that will populate all the other columns in the table!
    entityManager.persist(customer);
    entityManager.getTransaction().commit();
    }
    }

    }
  5. Run the application again and add a new customer to the database.

Delete

In this section, let the user delete a selected entry in the database. Using the concepts and code outlined above, implement the Delete action yourself.

  1. Create a new action, DeleteAction. Decide whether you want to bind it to a Customer node or whether you'd rather bind it to the toolbar, the menu bar, keyboard shortcut, or combinations of these. Depending on where you want to bind it, you will need to use a different approach in your code. Read the article again for help, especially by looking at how the "New" action was created, while comparing it to the "Refresh" action on the root node.

  2. Get the current Customer object, return an 'Are you sure?' dialog, and then delete the entry. For help on this point, read the article again, focusing on the part where the "Save" functionality is implemented. Instead of saving, you now want to delete an entry from the database.

See Also

This concludes the article. You have learned how to create a new NetBeans Platform application with CRUD functionality for a given database. You have also seen many of the NetBeans APIs in action. For more information about creating and developing applications on the NetBeans Platform, see the following resources:

Published at DZone with permission of its author, Geertjan Wielenga.

Comments

Craig Ringer replied on Wed, 2009/12/09 - 12:17am

This example doesn't appear to take the need to avoid blocking the UI while performing database work into account. While that keeps it simple, it also makes it a fairly useless example of using the platform in practice, as such concurrency issues are crucual when doing database work.

Geertjan Wielenga replied on Wed, 2009/12/09 - 12:27am

Excellent feedback, ringerc. That will be fixed. Thank you. One approach is to register actions in the layer file which then enables you to add an attribute to the layer entry. That attribute causes the action to be processed asynchronously, (which is a new feature in 6.8, i.e., the ability to mark an action as being asynchronous). These asynchronous actions can simulate SwingWorker:

class MyAction implements ActionListener, Runnable {
public MyAction(MyContext c) {
assert EventQueue.isEventThread();
// setup inside AWT thread, get what is important from c
}
public void actionPerformed(AE ev) {
assert !EventQueue.isEventThread();
// run off AWT thread
// perform the work
SwingUtilities.invokeLater(this);
}

public void run() {
assert EventQueue.isEventThread();
// finish in AWT and update the UI
}
}

 

Another approach would be to use SwingWorker. These approaches will be added to the article, though note that threading on the NetBeans Platform is also discussed here: http://wiki.netbeans.org/NetBeansDeveloperFAQ#Threading

Something else that's possible is to integrate with the NetBeans progress bar, which can be achieved with, literally, 3 lines of code.

Suraj Chhetry replied on Wed, 2009/12/09 - 4:04am

Thanks for great toturail. Could you tell me how can I create flollowing type of menu at TopComponent how can i do this ?

Root

----Customers

       - Greetjan        

             -Orders

                   +Raw-12092009

                   +Raw-11091009

             +Balance

             +Reports

 

Florian Brunner replied on Thu, 2009/12/10 - 5:42am

Hi Geertjan,

great to have another tutorial about this topic. Thanks!

Though I haven't read all of it yet, I already have one enhancement question:

As you know, the NetBeans IDE provides a project template to create the skeleton of a CRUD application based on the Swing Application Framework.

Maybe it would be useful to have a project template  to create the skeleton of a CRUD application based on the NetBeans Platform, too. What do you think?

 

-Florian

Geertjan Wielenga replied on Sun, 2009/12/13 - 6:51am

Hi Florian, that would be wonderful and is something I've been thinking of working on... sometime... when I have the time to do so... At least now there is a tutorial (the one to which these are the comments) describing how to do it and, yes, the next step would be to have a wizard that generates the code and you'd use the tutorial to understand what's been generated.

Dans Cut replied on Mon, 2009/12/14 - 10:40am

for geertjan....please reply my message please....I need your help...thanks u...

Geertjan Wielenga replied on Mon, 2009/12/14 - 12:06pm in response to: Dans Cut

I already replied. You want a CRUD tutorial, well, this IS a CRUD tutorial.

Geertjan Wielenga replied on Mon, 2009/12/14 - 6:56pm

Hi surajchchetry, that's a great idea. If I understand it correctly. This is the kind of project structure I am creating at the moment, for a new tutorial, based on your suggestion above.

A new tutorial should appear within the next week or two, to explain how to create project structures like the above, with a bunch of additional features too, as described here in my blog!

 

Nguyen Khiem replied on Mon, 2009/12/21 - 7:23am

hi, does it require jdk 6 for this ? i tried it on a mac ppc ( jdk5) and run into some problems while starting the app, mth like eclipselink cannot acces some libraries in javax.resources,** and unknown entity Customer. thanx

Kevin Jaques replied on Sun, 2010/01/03 - 12:25pm

In the part where you instruct us to create the CustomerChildFactory class, you should specify where (CustomerViewer, in org.shop.ui).

Kevin Jaques replied on Sun, 2010/01/03 - 12:47pm

In the Read Section, step 6, it says to put in several lines of codes somewhere in the TopComponent, but it didn't say where. In fact, all but one of those lines already existed. In fact, since it appears to be a replacement for the 'for' loop that we previously commented out, it would be far more clear to have left the 'for' loop in place till this step, then simply say, "In the constructor of the TopComponent, replace the 'for' loop with the following line:

em.setRootContext(new AbstractNode(Children.create(new CustomerChildFactory(resultList), true)));"

That also drives home part of the reason for the change.

Kevin Jaques replied on Sun, 2010/01/03 - 1:02pm

In the Read Section, step 7, you instruct us to run the Application. It won't compile till the imports are fixed. Ditto step 9.

Farouk Alhassan replied on Tue, 2010/01/19 - 3:08pm

Hi Geertjan

Thank you very much for such a great tutorial. Following the tutorials from here and the JPA intergration in the Definitive guide to Netbeans Platform I am trying to develop a real database application from the concepts explained. I am however not getting a any success.

In this tutorial, the EntityManager is created in the constructor of the TopComponent class which is not very efficient for obvious reasons and will also be a night mare to maintain if every TopComponent creates its own Entitymanager. I therefore tried the Installer approach used in the Netbeans Platform book but that didn't work. I kept getting ClasscastException when retreiving the objects via creating the nodes for the Viewer with ExplorerManager.

  protected boolean createKeys(List<Pupilidentifiers> list) {
      for (Pupilidentifiers identifier : resultList) {
        list.add(identifier);
      }
    return true;
  }

Que 1. What is the recommended way of using these API's and JPA in a production environment?

To get my application off the ground,

I have now moved the Node creation code to the componentOpened() method and calling the entity manager creation directly but that is throwing the following errors with regards

associateLookup(ExplorerUtils.createLookup(exm, map));

java.lang.IllegalStateException: Trying to set lookup ProxyLookup(class=class org.openide.explorer.DefaultEMLookup)->[org.openide.explorer.DefaultEMLookup$NoNodeLookup@5b695ffa, org.openide.util.Lookup$Empty@375212bc, org.openide.util.lookup.SingletonLookup@631c44f8] but there already is java.lang.ref.WeakReference@54f4289d for component: PupilViewer.PupilTopComponent[Pupil Window,0,0,0x0,invalid,layout=javax.swing.GroupLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=256,maximumSize=,minimumSize=,preferredSize=]
        at org.openide.windows.TopComponent.setLookup(TopComponent.java:1252)

Que 2. Is it not possible to call that method in the componentOpened() method?

Vladimír Duša replied on Tue, 2010/02/09 - 3:29pm

Hi Geertjan,

thanks for this super tutorial - it helped me a lot.

I still have a problem with saving the customer. The save button works as I expect, but the save action is not invoked during closing the TopComponent and switching between customers. After few hours of googling I have no Idea how to do it using SaveCookie and SaveCookieImpl model. Is there a possibility, to manually invoke the same save action as the save button? It would be good to invoke this save action in componentClosed() and resultChanged() methods.

Thank you very much

Vladimír Duša

John Hetherington replied on Wed, 2010/05/26 - 8:16pm

Started working through this article on Netbeans 6.8, completed the read section successfuly and got the tree displaying with the properties synchronised. Commenced on the update section and got down to Step 4 which states Go back to the Customer Viewer module and change the layer.xml file and specify that the CustomerTopComponent window will appear in the explorer mode.

 Has anyone the neccessary xml code to add here to make this happen as none is included in the article??

 Kind Regards

John In New Zealand

Ralph Lance replied on Tue, 2010/06/29 - 4:38am in response to: John Hetherington

Change the name attribute from "editor" to "explorer" under "Modes".

Hadi Setyono replied on Thu, 2010/07/01 - 5:32am

I want to make an application for user management with net beans. i read this article and i think that it can solve my requirement. can you show me the step how to make this application with netbeans with spring framework ?

Andreas Niepsch replied on Tue, 2010/07/20 - 6:02am

Hi Geertjan,

 

thank's for this tutorial. It's a very good start for developing  Rcp and Database-Applikations.

I have two questions:

1. If i close  "Customer Window" the content of "Editor Window" isn't clear, wy??? or what should i do?

I think if a TComponent is closed  the Lookup of is is not longer in the Global Context and not displayed in

the "Editor Windows" ????

 

2. The save-button is enabled if i mouseClicked in  "Editor Window". Enabling if changed content of the

form  is better in this sample.

 

 

Thank you

 Andreas

 


 

 

Craig Ringer replied on Tue, 2010/07/27 - 2:41am

There are issues with driving Swing directly with JPA entities when you start doing anything non-trivial, involving larger amounts of data. You start to need to lazily load parts of entities or entity relationships, and have to worry about how much data you're retaining in memory at once. This gives rise to issues with EDT blocking again, and major problems with managing JPA session lifetimes.

If you're going to be working with enough data that you don't want to download it from the database server all at once, think very carefully about whether this is the approach for you.

Anyone considering writing a non-trivial app driven directly by JPA data access should read this excellent article:

http://blog.schauderhaft.de/2008/09/28/hibernate-sessions-in-two-tier-rich-client-applications/

 ... and possibly my own inferior writing on the topic, which covers some issues not considered by the above link:

 http://soapyfrogs.blogspot.com/2010/07/jpa-and-hibernateeclipselinkopenjpaetc.html

 The only solutions I've found to the issues involve writing a (probably complex and boilerplate-heavy) mid-tier to buffer between Swing and JPA.

Craig Ringer replied on Tue, 2010/07/27 - 2:57am in response to: Farouk Alhassan

@gcameo: I'm not the smartest developer around, nor the strongest JPA expert, but my personal advice after recent experience trying to use JPA in a Swing app is: run, run, as fast as you can.

You'll have to write a midlayer to mediate between Swing and your JPA data access to get acceptable performance, avoid blocking the UI, etc. Even then it'll be "interesting" to manage JPA session lifetimes. I'm currently seriously considering ripping JPA out of my app entirely and going back to JDBC, because I'm finding it creates more problems than it solves in a 2-tier Swing app.

I'd be glad to be proved wrong, of course. Just so long as that "wrong" doesn't involve some comment about how you should "obviously" write a 3-teir appserver based monstrosity that communicates with the Swing rich client via RMI. I don't have an army of bored coders who need make-work, I need to get a real application written ;-)

I have direct personal messages enabled, and my email address is:

python -c "print 'Y3JhaWdAcG9zdG5ld3NwYXBlcnMuY29tLmF1\n'.decode('base-64')"

I don't seem to get email comment reply notifications, though.

Tj Harple replied on Tue, 2011/02/15 - 5:05pm

Hi Geertjan

Thank you very much for such a great tutorial. This is only my 2nd tutorial with Java 1.6.0_23 & NetBeans 6.9.1 on Windows 7. I was following the tutorial here : http://platform.netbeans.org/tutorials/nbm-crud.html

and had a strange issue for which only by chance I found the work around here on dzone.

My issue:

cannot find symbol
symbol  : method actionsGlobalContext()
location: class javax.swing.text.Utilities
      result = Utilities.actionsGlobalContext().lookupResult(Customer.class);

Which was worked around by the change:

 result = WindowManager.getDefault().findTopComponent("CustomerTopComponent").getLookup().lookupResult(Customer.class);

But my question...

Clearly it looks like I was missing a library dependencey. But when looking all over the internet, no one else had this issue, or spoke about using actionsGlobalContext with a specific dependency.

Is this a resent change that you may be aware of, or does it sound like my configuration may be suspect.

Can you suggest or point me to a resource which would allow me to figure out these types of dependencies on my own. In other words which file located in which directory contains this method.

 Also, I have noted a few minor changes needed in the netbean.org tutroial based on my configuration and would be willing to update or provide suggestion if that was appropriate. Is that work done here on dzone or via netbeans.org?

Thanks in Advance

Terry Harple

 

 

 

Mark Green replied on Sat, 2011/07/30 - 8:18pm

In Step 6.  How does the company name get to the node?  How do you specify which field to use?  Try another table and see!

Johnson Eyo replied on Wed, 2011/08/24 - 5:48am

i need some update on why netbans module should be used instead of a basic java desktop application,i noticed the new module project after been build might require you to install.pls anyone help,need to be clear

Johnson Eyo replied on Tue, 2011/09/13 - 3:50am

my program still refuses to build the customerlibrary to a jar file,i get these errors onh the console window,

 

init:
deps-clean:
Updating property file: C:\CustomerLibrary\build\built-clean.properties
Deleting directory C:\CustomerLibrary\build
clean:
init:
deps-jar:
Created dir: C:\CustomerLibrary\build
Updating property file: C:\CustomerLibrary\build\built-jar.properties
Created dir: C:\CustomerLibrary\build\classes
Created dir: C:\CustomerLibrary\build\classes\META-INF
Copying 1 file to C:\CustomerLibrary\build\classes\META-INF
Created dir: C:\CustomerLibrary\build\empty
Created dir: C:\CustomerLibrary\build\generated-sources\ap-source-output
Compiling 2 source files to C:\CustomerLibrary\build\classes
Note: Creating non-static metadata factory ...


An annotation processor threw an uncaught exception.
Consult the following stack trace for details.
java.lang.NoSuchMethodError: javax.annotation.processing.RoundEnvironment.getRootElements()Ljava/util/Set;
    at org.eclipse.persistence.internal.jpa.modelgen.MetadataMirrorFactory.setEnvironments(MetadataMirrorFactory.java:297)
    at org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor.process(CanonicalModelProcessor.java:368)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:634)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:565)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:704)
    at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:913)
    at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:659)
    at com.sun.tools.javac.main.Main.compile(Main.java:327)
    at com.sun.tools.javac.main.Main.compile(Main.java:253)
    at com.sun.tools.javac.main.Main.compile(Main.java:244)
    at com.sun.tools.javac.Main.compile(Main.java:69)
    at com.sun.tools.javac.Main.main(Main.java:54)
C:\CustomerLibrary\nbproject\build-impl.xml:603: The following error occurred while executing this line:
C:\CustomerLibrary\nbproject\build-impl.xml:245: Compile failed; see the compiler error output for details.
BUILD FAILED (total time: 7 seconds)

 

please help with these, because of this i can continue the rest of the tutorial

 

http://platform.netbeans.org/tutorials/nbm-crud.html

Carla Brian replied on Sun, 2012/05/06 - 7:32am

Once the data access module is part of our application, we create a new module that provides the user interface for our application. The new module gives the user a tree hierarchy showing data from the database. - Incredible Discoveries

Berton Jain replied on Sat, 2012/07/14 - 2:07am

Yes i am developing a application form y desktop and i am facing a problem. I read your solution but having some issues in line number 13 and 14. I want to have dress shop back ground with the theme of bride dresses. So is it possible?

Steve Sdas replied on Tue, 2012/09/25 - 9:06am

Once the above modules are part of our application, we create a new module that provides the user interface for our application.Las Vegas

Steve Sdas replied on Wed, 2012/09/26 - 2:44pm

Open some of the windows, undock them, and get to know the basic components that the NetBeans Platform provides without you doing any work whatsoever.Best Jogging Stroller Reviews

Steve Sdas replied on Thu, 2012/10/04 - 5:24am

These days I came across your site site and I discovered it is as one of the best no cost sources available ! Well done ! Keep on this good quality.best abs workout for men

Steve Sdas replied on Sun, 2012/10/07 - 1:04pm

Thanks for the information you post. I just subscribe your blog. This is a nice blog.high protein in urine

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.