Saturday Aug 01, 2015

New NetBeans Books in 2015

Each year brings new books about NetBeans. That's a given, at this point in time. This year's crop is particularly fine, with Apress, Packt, and Murach all bringing out completely new titles around NetBeans. Jump in, the water's fine, there's something for everyone:

And maybe there are others that I've left out here? Let me know! We'd love to promote any new book that is either about NetBeans or that uses or refers to NetBeans in one way or another. 

Friday Jul 31, 2015

My Current NetBeans Look

Quite happy with it. I set --fontsize 14 in 'netbeans.conf' file and am using the first of the two Dark Look and Feel Themes, from the plugin of the same name in the Plugin Manager. Also, Consolas 18 Bold is the font I am using. Click to enlarge the image below to get the complete impression:

Thursday Jul 30, 2015

Cassandra in NetBeans Databases Node

Now the Cassandra node is correctly located within the Databases node:

Sources of the plugin are here: https://github.com/GeertjanWielenga/NetCassandraBeans

Wednesday Jul 29, 2015

Selenium for Java in NetBeans IDE

Selenium is a popular browser automation framework. There's a good introduction and examples here. Let's see how to use it in NetBeans IDE, for Java applications, without installing plugins. 

In the upcoming NetBeans IDE 8.1 (already available as development builds), create your Maven Java EE project, which will give you this:

In the New File dialog, you'll find Selenium test files:

When you select the Selenium Test Case above and click Next and complete the wizard, you'll have the new Selenium test file, as well as all the dependencies you'll need (click to enlarge the image below):

Right-click the application, choose test file, the rest runs, the browser opens, and the results are shown in the Test Results window.

Tuesday Jul 28, 2015

YouTube: Crossroads.js for Enterprise JavaScript Applications

A common routing solution for JavaScript applications is Crossroads.js. Using this blog entry, here's how to understand and get started with Crossroads.js:

Watch more NetBeans videos here: https://www.youtube.com/user/NetBeansVideos

Monday Jul 27, 2015

Cassandra Meets NetBeans IDE

Initial support for Cassandra in NetBeans IDE 8.0.2 is available. Get it here:

http://plugins.netbeans.org/plugin/59444

Install into NetBeans IDE 8.0.2, open the Services window (Ctrl-5), right-click the Cassandra node, fill in a host (127.0.0.1 is the default), and a port (9042 is the default), and then browse the Cluster.

In the screenshot above "Explore From Here" opens the Cassandra node in a separate window, i.e., giving you more space, if you don't want to work in the Services window.

Double-click a table in a user keyspace (or right-click on it) to view its values in a table, as shown below. Choose "Dump Data" to print values into the Output window (Ctrl-4). Tables in system keyspaces are locked, i.e., data cannot be viewed.

In a future release of the plugin, the Cassandra node will be within the Databases node in the Services window, also Cassandra QL will be supported.

Sources are here, please fork and enhance: https://github.com/GeertjanWielenga/NetCassandraBeans

Sunday Jul 26, 2015

Viewing Cassandra Data in NetBeans IDE

Here's the latest status of Cassandra integration in NetBeans IDEyou can now open data into a sortable table or dump it into the Output window:

Source code is here for anyone who wants to contribute:

https://github.com/GeertjanWielenga/NetCassandraBeans

Saturday Jul 25, 2015

Setting Up an Environment for Cassandra/NetBeans Integration Development

After JCrete, a problem in continuing to work on the NetBeans/Cassandra plugin was that I didn't have Sven Reimers sitting next to me with his Cassandra cluster to which I connected for test data. So I had to set up a Cassandra cluster myself. Not a big problem with these instructions. Then I used the Cassandra Shell to create a keyspace, as described here. I liked the video data that Sven had available, so I used these Cassandra query scripts to recreate those, again via the Cassandra shell.

I also found the DataStax OpsCenter handy for taking a look at the structures I had created at this point:

Since I now had a running Cassandra cluster with live data, I was able to continue developing the plugin for NetBeans. As you can see, I can see the various structures from Cassandra in NetBeans, with some enhancements from last time, such as that the system keyspaces are separated from the user keyspaces (which will enable separate functionality for the user keyspaces) and that the data types are shown on the column nodes:

Next step is to find a nicer way to display the data from the user keyspaces. As you can see above, right now, everything is printed (neatly) into the Output window, ultimately some kind of grid is needed, maybe some kind of JavaFX component.

But the main win for the moment is that I now have a Cassandra cluster set up, with real data, that can be used while I continue developing the NetBeans plugin for Cassandra.

All the code for the plugin is available here: https://github.com/GeertjanWielenga/NetCassandraBeans

Friday Jul 24, 2015

Reverting Deleted Files

While checking the sources of the Cassandra/NetBeans integration into GitHub yesterday, something went very badly wrong and ALL the source files in my Maven project disappeared! Luckily I still had the Maven 'target' folder, which was untouched, I frantically searched for a Java decompiler online, decompiled the Java classes from the 'target' folder and then recreated my Maven project and eventually checked that in.

When I told Sven Reimers about this, he pointed out that in the IDE you can use the handy "Revert Deleted" feature. Let's say this is your project:

Now delete the Java source file you see above and right-click on the package (or anywhere in the ex-file's hierarchy) and choose History | Revert Deleted:

Hurray... there's the file again, the IDE still knows that the file existed:

Click OK above and your file is neatly returned to you, with all the content, and in the place, it originally had. Even after restarting the IDE, you'll still be able to do the above. Where is all this information stored? In the NetBeans cache directory (which is different to the NetBeans user directory), so, if you delete that directory, the information of deleted files will be lost and you'll not be able to revert again.

As a final step, go to the Options window and map "Revert Deleted" to a keyboard shortcut to make it an even faster process.

Of course, you should check things into a repository, e.g., GitHub. But normally, as in my case, you only put your GitHub repository together after you have created something significant enough to commit. If something, whatever it is, goes wrong during that initial process, the above procedure is extremely powerful, of course, and absolutely essential in these kinds of dire circumstances.

Thursday Jul 23, 2015

Cassandra in NetBeans IDE at #jcrete

Here at JCrete in a hacker session with Pierre Laporte (@pingtimeout), Sven Reimers (@svennb), and Thomas Darimont (@thomasdarimont) we managed to put together the start of Cassandra integration in NetBeans IDE.

The Cassandra Driver Core API is really cool and simple to use and in almost no time at all we were able to connect to a Cassandra cluster on Pierre's machine, to which Sven and Thomas were connected as hosts. Look in the Services window below and you'll see the Cassandra node, with one connected host listed, together with tables made available by the cluster, as well as the possibility of displaying data. The data visualization is the next part to work on, probably in an OutlineView.

Source code is here:

https://github.com/GeertjanWielenga/NetCassandraBeans

A potential next feature after that is syntax coloring for Cassandra Query Language, here's the ANTLR for that:

https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/cql3/Cql.g

Wednesday Jul 22, 2015

Complex Node Hierarchies

When you're using the Nodes API, things can become a bit tricky, especially when you want to visualize different Node types on the same level within a hierarchy.

As an example, let's imagine our domain model represents music bands, e.g., 'Oasis', etc. Here's a very simple node hierarchy that simply lists the names of the bands, i.e., each Node below visualizes an underlying Band object that is defined by a name:

After you've done the above, you want to show the members of the band. So, now the Band object is defined by a name and a list of Members:

However, let's say each Band has a list of Members, as well as one Manager. Here things start getting a bit tricky. The ChildFactory class has a 'createNodesForKey' method that returns multiple Nodes, so your inclination would be to use that, something like this:

@Override
protected Node[] createNodesForKey(Band key) {
    int size = key.getMembers().size() + 1;
    Node[] nodes = new Node[size];
    for (int i = 0; i < key.getMembers().size(); i++) {
        try {
            nodes[i] = new MemberNode(key.getMembers().get(i));
        } catch (IntrospectionException ex) {
            Exceptions.printStackTrace(ex);
        }
    }
    try {
        nodes[size-1] = new ManagerNode(key.getManager());
    } catch (IntrospectionException ex) {
        Exceptions.printStackTrace(ex);
    }
    return nodes;
}

What the above gets you is a structure like this:

However, you're more likely to want the structure below instead, i.e., a container Node for all the Members, together with a leaf Node for the Manager, of which there will always be one:

To achieve the above, I learned this approach from Sven Reimers during JCrete:

public class MusicBandContainerChildFactory extends 
    ChildFactory<MusicBandContainerChildFactory.Container> {
    
    private final Band band;

    public enum Container {
        MEMBERS, MANAGER
    }
    
    public MusicBandContainerChildFactory(Band band) {
        this.band = band;
    }

    @Override
    protected boolean createKeys(List<Container> list) {
        list.add(Container.MEMBERS);
        list.add(Container.MANAGER);
        return true;
    }
    
    @Override
    protected Node createNodeForKey(Container key) {
        switch (key) {
            case MEMBERS: {
                try {
                    return new MemberContainerNode(key);
                } catch (IntrospectionException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
            case MANAGER: {
                try {
                    return new ManagerNode(key);
                } catch (IntrospectionException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        }
        return null;
    }
    
    private class ManagerNode extends BeanNode {
        public ManagerNode(Container key) throws IntrospectionException {
            super(key);
            setDisplayName("Manager: "+band.getManager().getName());
        }
    }
    
    private class MemberContainerNode extends BeanNode {
        public MemberContainerNode(Container key) throws IntrospectionException {
            super(key, Children.create(new BandMemberChildFactory(band), true));
            setDisplayName("Members");
        }
    }
    
    private class BandMemberChildFactory extends ChildFactory<Member> {
        private final Band bean;
        public BandMemberChildFactory(Band bean) {
            this.bean = bean;
        }
        @Override
        protected boolean createKeys(List<Member> list) {
            list.addAll(bean.getMembers());
            return true;
        }
        @Override
        protected Node createNodeForKey(Member key) {
            BandMemberNode node = null;
            try {
                node = new BandMemberNode(key);
            } catch (IntrospectionException ex) {
                Exceptions.printStackTrace(ex);
            }
            return node;
        }
    }

    private class BandMemberNode extends BeanNode<Member> {
        public BandMemberNode(Member bean) throws IntrospectionException {
            super(bean, Children.LEAF);
            setDisplayName(bean.getName());
        }
    }
    
}

Thanks, Sven!

Tuesday Jul 21, 2015

Empty Node Populated On The Fly

Sometimes you need to create a Node that initially has no Children:

Later, when something has happened, e.g., as above, a menu item is clicked and a dialog is filled out, you want to populate the Node hierarchy:

How to achieve this?

Start by creating this class, to centrally manage changes:

import javax.swing.event.ChangeListener;
import org.openide.util.ChangeSupport;

public class PropertiesNotifier {
    private static final ChangeSupport cs = 
            new ChangeSupport(PropertiesNotifier.class);
    public static void addChangeListener(ChangeListener listener) {
        cs.addChangeListener(listener);
    }
    public static void removeChangeListener(ChangeListener listener) {
        cs.removeChangeListener(listener);
    }
    public static void changed() {
        cs.fireChange();
    }
}

Next, make sure that your Children are created only when a property change is received:

import java.beans.IntrospectionException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.nodes.BeanNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
import org.openide.util.NbPreferences;

class MusicBandChildFactory extends ChildFactory.Detachable<String> {
    private final List<String> bandNames;
    private ChangeListener listener;
    public MusicBandChildFactory() {
        this.bandNames = new ArrayList<String>();
    }
    @Override
    protected void addNotify() {
        PropertiesNotifier.addChangeListener(listener = new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent ev) {
                String bandName = 
                        NbPreferences.forModule(MusicBandsNode.class).
                                get("bandName", "error!");
                bandNames.add(bandName);
                refresh(true);
            }
        });
    }
    @Override
    protected void removeNotify() {
        if (listener != null) {
            PropertiesNotifier.removeChangeListener(listener);
            listener = null;
        }
    }
    @Override
    protected boolean createKeys(List<String> list) {
        list.addAll(bandNames);
        return true;
    }
    @Override
    protected Node createNodeForKey(String key) {
        BeanNode node = null;
        try {
            node = new BeanNode(key);
            node.setDisplayName(key);
        } catch (IntrospectionException ex) {
            Exceptions.printStackTrace(ex);
        }
        return node;
    }
}

Finally, fire a property change at an appropriate moment, such as when the user has entered something into a dialog:

import java.io.IOException;
import javax.swing.Action;
import org.netbeans.api.core.ide.ServicesTabNodeRegistration;
import org.openide.*;
import org.openide.actions.NewAction;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.util.NbBundle;
import org.openide.util.NbPreferences;
import org.openide.util.actions.SystemAction;
import org.openide.util.datatransfer.NewType;

@ServicesTabNodeRegistration(
        displayName = "#LBL_Bands",
        iconResource = "org/demo/enpotf/band.gif",
        name = "#LBL_Bands")
@NbBundle.Messages({"LBL_Bands=Music Bands"})
public class MusicBandsNode extends AbstractNode {
    public MusicBandsNode() {
        super(Children.create(new MusicBandChildFactory(), true));
        setDisplayName(Bundle.LBL_Bands());
        setShortDescription(Bundle.LBL_Bands());
        setIconBaseWithExtension("org/demo/enpotf/band.gif");
    }
    @Override
    public Action[] getActions(boolean context) {
        return new Action[]{SystemAction.get(NewAction.class)};
    }
    @NbBundle.Messages({
        "LBL_Title=Band Name Definition",
        "LBL_Text=Enter Band Name:"})
    @Override
    public NewType[] getNewTypes() {
        return new NewType[]{
            new NewType() {
                @Override
                public String getName() {
                    return Bundle.LBL_Title();
                }
                @Override
                public void create() throws IOException {
                    NotifyDescriptor.InputLine msg = new NotifyDescriptor.InputLine(
                            Bundle.LBL_Text(),
                            Bundle.LBL_Title());
                    Object result = DialogDisplayer.getDefault().notify(msg);
                    if (result == NotifyDescriptor.OK_OPTION) {
                        String bandName = msg.getInputText();
                        NbPreferences.forModule(MusicBandsNode.class).
                                put("bandName", bandName);
                        PropertiesNotifier.changed();
                    }
                }
            }
        };
    }
}

Sunday Jul 19, 2015

JMeter, Maven, and NetBeans IDE

Register the JMeter Maven plugin in your POM:

http://jmeter.lazerycode.com/

https://wiki.apache.org/jmeter/JMeterMavenPlugin

Then create a folder 'src/test/jmeter' in your Maven project. Install the JMeter plugin from Tools | Plugins and create a new JMeter Plan in the New File dialog (Ctr-N), in the 'src/test/jmeter' folder.

Build the project and notice that the JMeter Plan is run (click to enlarge the image below):

That's it. You can now run JMeter Plans during your Maven processes in NetBeans IDE.

Saturday Jul 18, 2015

FAQ: JMeter and NetBeans IDE

I've been looking at JMeter in NetBeans IDE, there's some great documents available on this combination:

While setting up JMeter in NetBeans IDE, I encountered two problems that are both easy to resolve when you know about these solutions.

  1. The plugin takes a long time to install. Unpacking hangs at 67%, during the unpacking of 'org-netbeans-modules-loadgenerator.nbm'. When this happens, don't worry, just wait a bit longer, for me it took about 10 minutes and then the installation succeeded. See here for this insight.

  2. The "External Edit" menu item fails to work. I.e, it's very convenient that you don't need to install JMeter yourself, but very inconvenient that the JMeter installation that the NetBeans JMeter plugin installs for you doesn't start up. Following these instructions, I ran the 'jmeter.bat' in the NetBeans user directory, found on the command prompt what the problem was, and then opened jmeter.bat and deleted the line 'set EVACUATION=-XX:MaxLiveObjectEvacuationRatio=20%'.

That's it. Now you're ready to use JMeter in NetBeans IDE.

Friday Jul 17, 2015

Getting Started with Arquillian in NetBeans IDE

Arquillian is JUnit for Java EE applications. (Plus more.) Read all about its features here. Markus Eisele wrote an article about the usage of Arquillian with NetBeans, sometime ago, here:

http://blog.eisele.net/2012/01/arquillian-with-netbeans-glassfish.html

I took a look at Arquillian today, via a new Maven project that Aslak Knutsen from Arquillian has made available here:

https://github.com/aslakknutsen/arquillian-example-helloworld

Simply git the above and then go to File | Open Project in NetBeans and point to the folder that contains the POM. Because NetBeans is smart and able to recognize and parse the POM, it will open the Maven project and visualize its structure automatically, no import process of any kind is needed. Play around with the test class in the Maven project, i.e, add some new tests to it for the simple CDI sample or change the existing test, and then right-click the project and choose Test (Alt-F6). You'll see the integration of Arquillian with NetBeans IDE, i.e., the tests are run and the results are shown, as you can see here (click to enlarge the image):


Next, you can integrate with JaCoCo, to see your code coverage, as described here.

On Windows, I encountered the problem described here, which I resolved as described there, i.e., I set 'jbossHome' in the 'arquillian.xml' file. Then the first time the tests are run, there's a failure because WildFly cannot be found because it hasn't been downloaded yet. Next time you run the tests, the server is downloaded, thanks to Chameleon, and the 'jbossHome' property points to the correct location, i.e., in the 'target' folder and is then able to run the tests.

Thursday Jul 16, 2015

New Book: Learn Java with NetBeans IDE

"We chose NetBeans because we think it's the best IDE for beginners and because it will help you to learn faster. It's also easy to use, free, and runs on all operating systems."

In the latest big fat (660 pages) Murach book, NetBeans IDE plays a key role:


The cover features NetBeans quite prominently:


Get it here: https://www.murach.com/shop/murachs-beginning-java-with-netbeans-detail

Wednesday Jul 15, 2015

New JavaScript Formatting Features in NetBeans IDE 8.1 (Part 3)

Here's the new Braces formatting feature for JavaScript files in NetBeans IDE 8.1:

Tuesday Jul 14, 2015

New JavaScript Formatting Features in NetBeans IDE 8.1 (Part 2)

Here's the new Alignment formatting feature for JavaScript files in NetBeans IDE 8.1:

Monday Jul 13, 2015

New JavaScript Formatting Features in NetBeans IDE 8.1 (Part 1)

In NetBeans IDE 8.0.2, these are the Formatting options that relate to JavaScript files:

Notice that in NetBeans IDE 8.1, new features have been added here:

In the next two blog entries, we'll look at the new features added above.

Friday Jul 10, 2015

Refactoring Java in NetBeans IDE 8.1 vs. 8.0.2

It may seem small, but it can be very powerful, once you learn the new keyboard shortcuts... refactoring in the next release of NetBeans:

Compare that to the current release of NetBeans, where the majority of the keyboard shortcuts above are not present:

About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« August 2015
SunMonTueWedThuFriSat
      1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
     
Today