Wednesday Apr 30, 2014

Leipzig Learns How to Extend NetBeans IDE

Sometime ago a training course for the NetBeans Platform was held in Leipzig, Germany. Excellently organized by Benno Markiewicz (he reports on this event here), who won the NetBeans community award last year for the many patches he provided, as well as the many issue reports, and his work in the NetCAT project, the course was held at the company where he works, ECG Erdgas Consult GmbH

The group was from a variety of different places, including the Laboratory for Machine Tools and Production Engineering at RWTH Aachen University (where some great work is being done with the NetBeans Platform) and the Frauenhofer Institute for Technology in Kaiserslautern.

As always, it was a great time, focused on modules, TopComponents, Nodes, Lookup, and all the other NetBeans APIs, with many exercises and hands on work, with the view from the front of the room on the group being more or less like this:

A full report on the training course can be found here:

I like this part of the report especially:

Zum Abschluss kann man sagen, dass sich der Kurs hinsichtlich Kenntnisse über NetBeans und dem Kennenlernen einer wunderschönen Stadt mehr als gelohnt hat. Wir möchten die Erfahrungen nicht mehr missen, denn auch unsere Gruppendynamik hat sich dadurch sehr verbessert.

Two plugins have already been created by participants on the course:

As always, the highlight of the days spent in Leipzig were the informal chats and hanging out with beers, sushi, and similar items, in interesting places.

Again, it was excellently organized by Benno, as I am sure everyone will agree, and here's a final pic, showing Benno, me, Reinhard (who joined the course from Luxemburg, to make stock trading software), and Toni:

After the course, HTWK Leipzig, which is the Leipzig University of Applied Science, hosted a NetBeans Platform session entitled "Lessons Learned in Software Development at Boeing, NASA, and Other Large Organizations", where the focus was on modularity and loose coupling and the other features provided out of the box by the NetBeans Platform. Many thanks to Prof. Karsten Weicker and, again, Benno for organizing this interesting session.

Are there other groups out there interested in learning about the NetBeans APIs that constitute NetBeans IDE and any other modular application that makes use of the NetBeans Platform?

Tuesday Apr 29, 2014

Dustin Marx Book Review on "NetBeans Platform for Beginners"

Great book review on "NetBeans Platform for Beginners":

But that's just the start. The whole thing is here:

Monday Apr 28, 2014

AngularJS Seed, Bower, and NetBeans IDE 8

Pulling in project templates from online repos that we, that is, the NetBeans team, have no control over has pros and cons. One clear con is that when things change a lot in those online repos, we're basically screwed. We've had fun with that with Cordova as well over the past NetBeans releases.

And that's what happened recently when Bower was suddenly and mysteriously, from my point of view anyway, added to the fun that is the AngularJS Seed template. Now, whenever you pull the AngularJS Seed template, whether on your own via whatever means, or via the NetBeans template for this purpose, you'll find you have references to angular.js and angular-route.js that look like this, in the index.html file:

<script src="../bower_components/angular/angular.js"></script>
<script src="../bower_components/angular-route/angular-route.js"></script>

That's wonderful, assuming the project already has the above files in the above folders. But it doesn't. You need to set up Bower and then manually (or maybe the NetBeans infrastructure should do that for you) call "bower install angular" and "bower install angular-route" in the appropriate location in your project.

So, what I did to get it all working was:

  1. Uninstall 'nodejs' and uninstall 'npm'. And then I hunted through all the nooks and crannies of my system for any remaining artifacts, e.g., the '.npm' folder in your user directory, which I then also deleted. The reason? Well, Bower doesn't install if your version of nodejs is not one of the latest versions, hence a reinstallation of nodejs is needed, followed by a reinstallation of npm.

  2. Great. Now you can call 'npm install -g bower', which will then cause Bower to be installed correctly (all messages green in the command prompt). Make sure to include 'g', which means 'global', otherwise Bower will install into the directory where you run the command, instead of in the global location for all node modules. Then, before continuing, run 'bower' on the command line to make sure it works.

  3. Hurray. Then create a new HTML5 project in NetBeans IDE 8, while making use of the AngularJS Seed template.

  4. Now go to the command line, to the 'app' folder in the project you created above and then run 'bower install angular' and 'bower install angular-route'. You need to do this in the 'app' folder. You'll now end up with a folder called 'browser_components' in your 'app' folder, containing two subfolders with the JS and other artifacts for the references in the index.html file.

  5. Finally, tweak the index.html file so that there are no relative references anymore (needed if you're using the embedded browser, because the embedded server doesn't serve outside of the 'app' folder, which is maybe a limitation of that server that should be fixed):

    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/angular-route/angular-route.js"></script>

And now everything is OK again. You can run the project as before and you have the start of your AngularJS application. Below you see the Files window, i.e., how things look on disk, followed by the logical view provided by the Projects window:

Related reading that I found helpful in getting the above put together:

Related issue and other comments:

Friday Apr 25, 2014

New YouTube Tutorials on "Java And, Obviously, NetBeans"

Nice starting sentence to an interesting new YouTube tutorial published today: "In today's lesson we're going to learn how to create a very simple but functional MP3 player in Java and, obviously, NetBeans":

This is part of an AWESOME set of YouTube tutorials all about using "Java and, obviously, NetBeans" to create really cool applications:

Related website:

Thursday Apr 24, 2014

Meaningful HTML/Java DukeScript Framework Applications (Part 2)

OK, so now the application I started working on is even more meaningful.

Firstly, what is it all about? Well, with the DukeScript Framework, you use Java to write application logic, with HTML5 to render the UI. No Swing. No JavaFX. HTML takes the place of those toolkits. Then you can manipulate the HTML page from Java, use REST or WebSockets, and do anything else with Java that you might want to do.

So here's the state of my CRUD app right now, i.e., still only R, but with improved code (thanks Jarda), and now the selected customer is displayed when a row is selected. 

Let's start by looking at the HTML file that defines the above.

        <h1>Sample Database</h1>
        <table border="1">
            <tbody data-bind="foreach: customers">
                <tr data-bind="click: $root.selectCustomer" style="cursor: pointer">
                    <td data-bind="text: name"></td>
                    <td data-bind="text: city"></td>
                    <td data-bind="text: state"></td>
                    <td data-bind="text: email"></td>
        <b>Current Selection</b>
        <p data-bind="with: selectedCustomer">
            <font color="red">Name</font>: <span data-bind="text: name"> </span>
            <font color="red">City</font>: <span data-bind="text: city"> </span>

What you see here is plain HTML together with Knockout bindings. The rows in the table are bound to properties in the model. When a row is selected, a method in the model is called that changes a property, which is bound with the Knockout "with" binding so that the currently selected name and city are shown.

Here's the definition of the Main class, which is annotated with the @Model annotation, and can be understood as a singleton:

@Model(className = "CrudApp", properties = {
    @Property(name = "selectedCustomer", type = CustomerData.class),
public final class Main {
    static java.util.List<CustomerData> customers() {
        EntityManager entityManager
                = Persistence.createEntityManagerFactory("myPU").
        Query query = entityManager.createNamedQuery("Customer.findAll");
        List<CustomerData> arr = new ArrayList<>();
        for (Object object : query.getResultList()) {
            arr.add(((Customer) object).getData());
        return arr;
    static void selectCustomer(CrudApp myModel, CustomerData data) {
    private Main() {
     * Launches the browser
    public static void main(String... args) throws Exception {
                invoke("onPageLoad", args).
     * Called when page is ready
    public static void onPageLoad(String... args) throws Exception {
        new CrudApp().applyBindings();

There's also a Customer POJO, i.e., a JPA entity, which in addition to the JPA annotations is annotated as follows:

@Model(className = "CustomerData", properties = {
    @Property(name = "name", type = String.class),
    @Property(name = "addressline1", type = String.class),
    @Property(name = "addressline2", type = String.class),
    @Property(name = "city", type = String.class),
    @Property(name = "state", type = String.class),
    @Property(name = "phone", type = String.class),
    @Property(name = "fax", type = String.class),
    @Property(name = "email", type = String.class),
    @Property(name = "creditLimit", type = int.class)

Plus, there's a getter that returns the CustomerData, so that the "customers()" method in the Main class can build up the list of customers.

The next step is to persist the data back into the database. Weird to be manipulating the DOM from Java but, obviously, great. 

Wednesday Apr 23, 2014

Register Today for Virtual Developer Day!

Virtual Developer Day: Java 2014 is on May 6th (Americas), May 14th (EMEA), and May 21st (APAC).

Hear from experts on Java SE 8, Java EE 7, and Java Embedded.

Watch tutorials from the experts to improve your expertise in Java, and ask questions during live chats. This FREE virtual event will cover:

  • Java SE 8 New Features: Lambdas and more
  • The latest on the Java EE 7
  • How Java makes it easy for you to control a wide range of embedded devices

Go here to register.

Tuesday Apr 22, 2014

Meaningful HTML/Java DukeScript Framework Applications (Part 1)

In an effort to make a meaningful application on the DukeScript Framework, here's the start of a JPA-based CRUD app (right now, only R is supported):

There are three parts to this.

  1. Model. I generated JPA entity classes from my database. I ended up with the "Customer" class, which has relationships with "DiscountCode" and "MicroMarket". Then I added a new annotation, on top of all the JPA annotations, to the "Customer" class:
    @Model(className = "CustomerData", properties = {})

    Then, in the same class, i.e., in "Customer", I exposed the data as follows:

    static java.util.List customers() {
        EntityManager entityManager
                = Persistence.createEntityManagerFactory("myPU").
        Query query = entityManager.createNamedQuery("Customer.findAll");
        return query.getResultList();
  2. Controler. In the Main class, I changed "onPageLoad" to this:
    public static void onPageLoad(String... args) throws Exception {
        new CustomerData().applyBindings();
  3. View. Finally, the "index.html" that is bound to the model is as follows:
            <h1>Sample Database</h1>
            <table border="1">
                <tbody data-bind="foreach: customers">
                        <td data-bind="text: $data.getName()"></td>
                        <td data-bind="text: $data.getCity()"></td>
                        <td data-bind="text: $data.getState()"></td>
                        <td data-bind="text: $data.getEmail()"></td>

Notice that the method "customers()" in the model is bound in the "foreach" in the view.

Probably I'm doing all kinds of things wrong. Probably I should be using properties in the model. Happy to be corrected. 

Monday Apr 21, 2014

Entity Expander for NetBeans IDE 8 (Part 5)

Now package-level expansion is supported:

When you select a template while on a package, as above, all Java classes within the package are all transformed at the same time, for example, choosing "Panel" above results in the below all being added in one go:

Go here to get it:

Sunday Apr 20, 2014

Themes for NetBeans JPA Modeler

The latest release, which came out today, of the awesome JPA Modeler plugin for NetBeans (by Gaurav Gupta) provides a theme switcher. Click to enlarge the image below.

Not one line of code in the many classes you see above was created by me. Instead, they were all generated from the diagram, which was generated from my database.

Get it here:

Saturday Apr 19, 2014

Entity Expander for NetBeans IDE 8 (Part 4)

Toni suggested it would be cool to create some templates for Nodes, ChildFactories, and TopComponents, on top of POJOs, for the Entity Expander that I blogged about last month

That way, NetBeans would have the start of something like EMF in Eclipse.

So, here are the templates I have so far.

Node ("BeanNode"):

package ${package};

import java.beans.IntrospectionException;
import java.util.List;
import javax.swing.Action;
import org.openide.nodes.BeanNode;
import org.openide.util.Utilities;

public class ${object}BeanNode extends BeanNode {
    public ${object}BeanNode(${object} bean) throws IntrospectionException {

    public Action[] getActions(boolean context) {
        List myActions = 
        return myActions.toArray(new Action[myActions.size()]);


Child Factory ("BeanChildFactory"):

package ${package};

import java.beans.IntrospectionException;
import java.util.List;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;

public class ${object}BeanChildFactory extends ChildFactory<${object}> {
    protected boolean createKeys(List<${object}> toPopulate) {
        //connect to data source
        //and populate "toPopulate" list
        return true;
    protected Node createNodeForKey(${object} key) {
        ${object}BeanNode cbn = null;
        try {
            cbn = new ${object}BeanNode(key);
        } catch (IntrospectionException ex) {
        return cbn;

TopComponent ("ViewerTopComponent"):

package ${package};

import java.awt.BorderLayout;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.explorer.ExplorerManager;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.NbBundle.Messages;

        preferredID = "${object}ViewerTopComponent",
        persistenceType = TopComponent.PERSISTENCE_ALWAYS
        mode = "explorer", 
        openAtStartup = true)
@ActionID(category = "Window", 
        id = "${package}.${object}ViewerTopComponent")
        path = "Menu/Window" /*, position = 333 */)
        displayName = "#CTL_${object}ViewerAction",
        preferredID = "${object}ViewerTopComponent"
    "CTL_${object}ViewerTopComponent=${object}Viewer Window",
    "HINT_${object}ViewerTopComponent=This is a ${object}Viewer window"
public class ${object}ViewerTopComponent extends TopComponent implements ExplorerManager.Provider {
    private ExplorerManager em = new ExplorerManager();

    public ${object}ViewerTopComponent() {
        setLayout(new BorderLayout());
        //somehow create your children:
        //Children.create(new MyChildFactory(), true);
        Node rootNode = new AbstractNode(Children.LEAF);

    public ExplorerManager getExplorerManager() {
        return em;


Friday Apr 18, 2014


With APIs from NetBeans IDE 8.0, there's the new annotations @PaletteItemRegistration and @PaletteItemRegistrations for registering items in a palette:

As you can see, you use the annotations in the class, which you can create by using the template Java | Java Package Info in the New File dialog.


Therefore, will need to update this tutorial with the new annotations:

Thursday Apr 17, 2014

Three Tips for DukeScript Fanboys

Here's my advice for DukeScript fanboys, of which there are some, but mainly two: Jaroslav Tulach and Toni Epple.

  1. Stop talking about "DukeScript". Whenever you say "DukeScript", any sane person assumes you're talking about a language. You're not. And that's what's confusing. You're talking about a framework. The DukeScript Framework is equivalent to HTML5 minus JavaScript plus Java. That's it. And that's a powerful message.

  2. Stop playing games. Instead, create real applications. Create CRUD applications, for example. Here's my humble first beginning, showing data from the Sample database in GlassFish displayed in HTML via Java in the JavaFX WebView thanks to the DukeScript Framework:

    But, please, make several complete scenarios that run out of the box, including, and especially, CRUD apps. This is where Vaadin and PrimeFaces have succeeded so far, i.e., they have complete widget samples, component demos, etc, etc, etc. Focus on business scenarios, not funny games.

  3. Seriously, sit down and think about all that stuff that you're exposing. Vaadin somehow gets away with it, because they're based on a known entity, i.e., GWT, and the DukeScript Framework should be able to do so, too. There's just so much going on in the background, it's scary. Somehow, you need to at least explain absolutely everything. Either shit or get off the pot, i.e., describe fully what's going on in the implementation or accept that it's going to be adopted by a small subset of developers. Since all the ideas in the DukeScript Framework are so completely brand new and so much magic is done via annotations, you either explain it all, down to the smallest details, or run the risk that no one will adopt it because, since there are several more understandable competitors, you're running the risk that something simpler, e.g., Vaadin, is going to become the standard, whether de-facto or not.
My two cents. And I have never been (very) wrong.

Wednesday Apr 16, 2014

Swedish Economy Modeling on the NetBeans Platform

WamSys AB, located in Gothenburg, Sweden, focuses on developing products with Oracle DB and the NetBeans Platform.

In particular, the NetBeans Platform is used as the basis of their Mozart Platform, which provides generic modules for custom Swing components, including a table component with support for grouping, "frozen" rows and columns, and built-in aggregates.

Furthermore, the Mozart Platform facilitates the building of products on top of it. For example, it has its own widget framework, providing a customizable start page comparable to a web portal, while the Options window manages look & feel properties, such as support for switching to the JTattoo look and feel.

Here you can see a YouTube clip of the Mozart table component:

And here is a YouTube clip of the Mozart dashboard:

One of the products based on the Mozart Platform is Mozart Economy, a fully customizable billing system able to calculate fees based on complex conditions and provide data for invoicing. The system is used by Swedish schools for calculation of fees paid in preschool, where many different factors affect the price, such as the child's age, family income, and number of hours at school. The module corrects invoices over any period back in time with respect to changed conditions over time.

Another part of the solution is Mozart Statistics, which retrieves data from a database and creates statistical reports in Microsoft Excel, using the Apache POI library.  This enables customers to get powerful statistical reports with pivot tables and various type of charts.

Tuesday Apr 15, 2014

DukeScript Framework for Dummies

Jaroslav Tulach's Java/JavaScript framework DukeScript explained for dummies (e.g., me):

Or watch it here:

Further info:

Monday Apr 14, 2014

Can it be true? HTML 4 Java, at last?

Two events recently conspired to make me suddenly understand Jaroslav Tulach's most recent amazing project. The first was a comment I received in this blog a few days ago:

I was wondering... why Java is not in a position where it is using HTML, CSS or Javascript for its GUI? Java Swing has lots of limitations for UI designers and also it is tedious. Frankly... it is old! Where using HTML bootstrap, CSS all of the UI requirements are already taken care of. I know that JavaFX introduced the web browser in Java and sadly attempted to introduce a FXML style GUI but it is a bit clunky. Bit unnecessary to learn something new with not much gain! Why not develop a solution where the front-end of a desktop java application will use HTML5 and the backend will use good old Java for carrying out bulk of the work. Java already has a great reputation... why not combine it with the best of HTML, CSS and Javascript for desktop applications?

 Now, I must say that I disagree with both points, i.e., re Swing and JavaFX, I think both are great, really great, no reservations on either of them... for the purpose for which they're intended to be used, i.e., for their place in the world, they serve that place well. However, let's leave aside that whole discussion for the moment and focus on the other point made above, that is, that HTML, especially the goodness of HTML5, could be an alternative way to provide a frontend on top of Java on the desktop.

The second event, which really brought the point home for me was an article that came through on Twitter entitled "Creating Desktop Applications With node-webkit". The article lists all the reasons why web applications can suck, e.g., "when using browsers one’s control of the user interface is limited", browser variance, and security issues. And then the Node WebKit is introduced, "to take the pain out of offline single-page application development".

 OK, now I get it. Java on the desktop is great, at last there's a general acceptance of that, as opposed to the continual process of throwing out the baby with the bathwater. However, what both these divergent sources are pointing out is that, in the same way that the Java EE world enjoys having the option of incorporating HTML5 front-ends, let's have the same opportunities for the Java desktop. 

And, with that background, let's take a look at Jaroslav Tulach's latest project. 

Start by cloning from Git, the following:

hg clone -r 7c26d20c0b0f 

What you now have 

Friday Apr 11, 2014

Python in NetBeans IDE 8.0

Update 10 December 2014: Please go to this blog entry to follow the steps and for all further discussion on NetBeans IDE and Python:

Thursday Apr 10, 2014

Context-Sensitive TopComponent (Part 2)

Another way a TopComponent can be context sensitive is in the requirement that the menubar and toolbar need to relate to a specific TopComponent. Below you see that when Win1 is active, a different group of menus and toolbars is available...

... than when Win2 is active:

Part of the solution to this is described here recently about multiple rows of toolbars. However, this only addresses the topic of toolbars. What about menubars? And maybe other components too? I.e., when a TopComponent is active, it would be great if a subfolder of the FileSystem would become enabled, while all other parts would become disabled.

The complete solution to this scenario has been described before, here. Jesse Glick has all the code for this here:

What the above lets you do is create layer entries like this:

<folder name="win1">
    <folder name="Menu">
        <folder name="First">
            <attr name="position" intvalue="150"/>
        <file name="Help.hidden"/>
    <folder name="Toolbars">
        <file name="UndoRedo.hidden"/>
<folder name="win2">
    <folder name="Menu">
        <folder name="Second">
            <attr name="position" intvalue="250"/>

Then, each TopComponent can specify which folder they want to own:

associateLookup(Lookups.singleton(new SystemSubPathLayerProvider("win1")));

The "SystemSubPathLayerProvider" does all the work in the background to enable and disable items appropriately, whether they are toolbars, menubars, or whatever else.

Nothing is written to disk, this is all done programmatically within the code, and not written to the user directory.

Wednesday Apr 09, 2014

Context-Sensitive TopComponent (Part 1)

I picked up a cool idea from a Polish developer, Dominik Cebula, recently. In the same way that the NetBeans Platform has context sensitive Actions, there should be context sensitive TopComponents.

Only if an Object of a specific type specified in the public constructor of the TopComponent is found in the Lookup should it be possible to open the TopComponent. And then the Object is available to the TopComponent, without the TopComponent needing to implement a LookupListener.

For example, below "FlightLeg Editor" and "Delay Editor" are both disabled, because no "FlightLeg" and no "Delay" is in the Lookup. Hence it doesn't make sense to open the editor, i.e., when the Object for which the editor exists is not available.

On the other hand, below a "FlightLeg" is available in the Lookup, because one of the flight legs has been selected and hence the underlying "FlightLeg" object is now in the Lookup. Therefore, the "FlightLeg Editor" menu item is enabled so that an editor can be opened for editing the selected flight leg:

In the same way, here the "Delay Editor" can be opened, because an Object of the type "Delay" is published when a DelayNode is selected:

Here is one of these TopComponents:

        preferredID = "FlightLegEditorTopComponent",
        persistenceType = TopComponent.PERSISTENCE_ALWAYS
        mode = "editor", 
        openAtStartup = false)
        category = "Window", 
        id = "")
        path = "Menu/Window")
        displayName = "#CTL_EditorAction",
        preferredID = "FlightLegEditorTopComponent"
    "CTL_EditorAction=FlightLeg Editor",
public class FlightLegEditorTopComponent extends ObjectTopComponent implements ActionListener{
    private FlightLeg fl;
    //no-arg constructor is required:
    private FlightLegEditorTopComponent() {}
    public FlightLegEditorTopComponent(FlightLeg fl) {
        this.fl = fl;
    public void actionPerformed(ActionEvent e) {

In the above, notice there is a public constructor that receives the domain object "FlightLeg" (i.e., for an airline-type application). Also, there's a new annotation up there, "@ObjectTopComponent.OpenActionForObjectRegistration".

Here's what that annotation looks like (copied and then simply renamed from "@TopComponent.OpenActionRegistration"):

public class ObjectTopComponent extends TopComponent {
    @Target({ ElementType.TYPE, ElementType.METHOD })
    public static @interface OpenActionForObjectRegistration {
        String displayName();
        String preferredID() default "";

However, the annotation above is processed in such a way that a context-sensitive Action is created that uses the type in the constructor of the TopComponent:

@ServiceProvider(service = Processor.class)
public final class ObjectTopComponentProcessor extends LayerGeneratingProcessor {
    public ObjectTopComponentProcessor() {
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> hash = new HashSet<String>();
        return hash;
    protected boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) throws LayerGenerationException {
        for (Element e : roundEnv.getElementsAnnotatedWith(ObjectTopComponent.OpenActionForObjectRegistration.class)) {
            ObjectTopComponent.OpenActionForObjectRegistration reg = e.getAnnotation(ObjectTopComponent.OpenActionForObjectRegistration.class);
            assert reg != null;
            Description info = findInfo(e);
            ActionID aid = e.getAnnotation(ActionID.class);
            if (aid != null) {
                File actionFile = layer(e).
                        file("Actions/" + aid.category() + "/" +'.', '-') + ".instance").
                        methodvalue("instanceCreate", "", "openAction");
                actionFile.instanceAttribute("component", TopComponent.class, reg, null);
                if (reg.preferredID().length() > 0) {
                    actionFile.stringvalue("preferredID", reg.preferredID());
                generateContext(e, actionFile);
                actionFile.bundlevalue("displayName", reg.displayName(), reg, "displayName");
                if (info != null && info.iconBase().length() > 0) {
                    actionFile.stringvalue("iconBase", info.iconBase());
        return true;
    private void generateContext(Element e, File f) throws LayerGenerationException {
        ExecutableElement ee = null;
        ExecutableElement candidate = null;
        for (ExecutableElement element : ElementFilter.constructorsIn(e.getEnclosedElements())) {
            if (element.getKind() == ElementKind.CONSTRUCTOR) {
                candidate = element;
                if (!element.getModifiers().contains(Modifier.PUBLIC)) {
                if (ee != null) {
                    throw new LayerGenerationException("Only one public constructor allowed", e, processingEnv, null); // NOI18N
                ee = element;
        if (ee == null || ee.getParameters().size() != 1) {
            if (candidate != null) {
                throw new LayerGenerationException("Constructor has to be public with one argument", candidate);
            throw new LayerGenerationException("Constructor must have one argument", ee);
        VariableElement ve = (VariableElement) ee.getParameters().get(0);
        TypeMirror ctorType = ve.asType();
        switch (ctorType.getKind()) {
            case ARRAY:
                String elemType = ((ArrayType) ctorType).getComponentType().toString();
                throw new LayerGenerationException("Use List<" + elemType + "> rather than " + elemType + "[] in constructor", e, processingEnv, null);
            case DECLARED:
                break; // good
                throw new LayerGenerationException("Must use SomeType (or List<SomeType>) in constructor, not " + ctorType.getKind());
        DeclaredType dt = (DeclaredType) ctorType;
        String dtName = processingEnv.getElementUtils().getBinaryName((TypeElement) dt.asElement()).toString();
        if ("java.util.List".equals(dtName)) {
            if (dt.getTypeArguments().isEmpty()) {
                throw new LayerGenerationException("Use List<SomeType>", ee);
            f.stringvalue("type", binaryName(dt.getTypeArguments().get(0)));
            f.methodvalue("delegate", "org.openide.awt.Actions", "inject");
            f.stringvalue("injectable", processingEnv.getElementUtils().getBinaryName((TypeElement) e).toString());
            f.stringvalue("selectionType", "ANY");
            f.methodvalue("instanceCreate", "org.openide.awt.Actions", "context");
        if (!dt.getTypeArguments().isEmpty()) {
            throw new LayerGenerationException("No type parameters allowed in ", ee);
        f.stringvalue("type", binaryName(ctorType));
        f.methodvalue("delegate", "org.openide.awt.Actions", "inject");
        f.stringvalue("injectable", processingEnv.getElementUtils().getBinaryName((TypeElement) e).toString());
        f.stringvalue("selectionType", "EXACTLY_ONE");
        f.methodvalue("instanceCreate", "org.openide.awt.Actions", "context");
    private String binaryName(TypeMirror t) {
        Element e = processingEnv.getTypeUtils().asElement(t);
        if (e != null && (e.getKind().isClass() || e.getKind().isInterface())) {
            return processingEnv.getElementUtils().getBinaryName((TypeElement) e).toString();
        } else {
            return t.toString(); // fallback - might not always be right
    private Description findInfo(Element e) throws LayerGenerationException {
        Element type;
        switch (e.asType().getKind()) {
            case DECLARED:
                type = e;
            case EXECUTABLE:
                type = ((DeclaredType) ((ExecutableType) e.asType()).getReturnType()).asElement();
                throw new LayerGenerationException("" + e.asType().getKind(), e);
        TopComponent.Description info = type.getAnnotation(TopComponent.Description.class);
        return info;

The above processor is a combination of the TopComponentProcessor and the ActionProcessor in the NetBeans Platform.

And now you have a layer generating processor that creates a context sensitive Action for opening a TopComponent. If no Object of the type specified in the constructor of the TopComponent is in the Lookup, the Action will be disabled. If an Object of the specified type is available, the Action is enabled and immediately available to the TopComponent as soon as it is opened.

That's an example of a view that is bound to a model. Useful for editors that need to be created for one or more specific Objects. Data binding for TopComponents, hurray.

Tuesday Apr 08, 2014

Disable Module on Authentication Failure

The user starts the application. The splash screen is shown. Right after the modules are loaded, as indicated by the text in the splash screen, a small login screen appears. The user fills in the wrong login credentials and clicks OK. The text in the splash screen shows that one or more modules are being turned off. Then the main window of the application appears. Because the login credentials were wrong, one or more of the modules have been disabled. 

import java.util.List;
import org.netbeans.api.autoupdate.OperationContainer;
import org.netbeans.api.autoupdate.OperationException;
import org.netbeans.api.autoupdate.OperationSupport;
import org.netbeans.api.autoupdate.UpdateElement;
import org.netbeans.api.autoupdate.UpdateManager;
import org.netbeans.api.autoupdate.UpdateUnit;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.modules.OnStart;
import org.openide.util.Exceptions;

public class Startable implements Runnable {
    public void run() {
        NotifyDescriptor.InputLine nd = new NotifyDescriptor.InputLine("Name", "Login");
        //Got tired of typing it by hand:
        Object response = DialogDisplayer.getDefault().notify(nd);
        if (response == NotifyDescriptor.OK_OPTION) {
            String username = nd.getInputText();
            NotifyDescriptor.Message msg;
            if (!username.equals("admin")) {
                List<UpdateUnit> updateUnits = 
                for (UpdateUnit updateUnit : updateUnits) {
                    //Get each module that is installed:
                    UpdateElement el = updateUnit.getInstalled();
                    //Of those that are installed, if it has the code name base
                    //of the module we are interested in, and it is enabled,
                    //continue with this procedure to disable it:
                    if (el != null
                            && el.getCodeName().equals("com.mycompany.admin")
                            && el.isEnabled()) {
                        try {
                            //Specify how we want to handle the module; 
                            //here, we want to disable it:
                            OperationContainer oc = OperationContainer.createForDirectDisable();
                            //Finally, do the operation,
                            //passing a progress handle or, as in this case, null:
                            OperationSupport supp = (OperationSupport) oc.getSupport();
                        } catch (OperationException ex) {

Finally, the module is not shown in the Plugin Manager, so that it cannot be enabled from there. Only if the user logs in correctly is the module enabled.

Related reading:

Monday Apr 07, 2014

Multiple Rows of Toolbars

Realized today that toolbars can be placed in different rows:

The above is a result of a file I named "All.xml" that has this content and is found in the same package as the layer.xml file:

<?xml version="1.0"?>
<!DOCTYPE Configuration PUBLIC "-//NetBeans IDE//DTD toolbar//EN"
        <Toolbar name="File" />
        <Toolbar name="UndoRedo" />
        <Toolbar name="Clipboard"/>
        <Toolbar name="Memory"/>

It is registered as follows in the layer.xml file:

<folder name="Toolbars">
    <file name="All.xml" url="All.xml"/>

And then, as a handy final step, here's code in one of my TopComponents for switching between different toolbar definitions:

protected void componentActivated() {
public void componentDeactivated() {

Here's some related reading:


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.


« April 2014 »