Saturday, March 10, 2012

Source code for NetBeans Actions solution

I just wanted to check back in and publish the source code for my solution to NetBeans' action paradigm issue that I talked about in this post.

AbstractActionDelegate.java
AbstractActionProvider.java
ActionProvider.java

Remember, objects listen to ActionProviders.  The ActionDelegate is the NetBeans-generated action.  If you have it extend AbstractActionDelegate, all it will do is notify its corresponding ActionProvider, which will in turn notify all listeners that an action has occurred.

Check out the unit test for AbstractActionDelegate to see an example of this in action.

Sunday, July 10, 2011

Finding the last match

One relatively common search that is unfortunately not provided by the Java Standard Library's Matcher is finding the last match of a regular expression.  The most common solution is to do something like:
int lastFind;
while (matcher.find()) {
    lastFind = matcher.start();
}
// Do things with lastFind...

That's fine as long as you only want the absolute last instance of a match.  However, if you want the last match in a particular range, that while loop becomes significantly more complicated. I found that out when I tried to implement a find previous function similar to Firefox's.

With some major help from this StackOverflow post I found a much better solution that uses a binary-like search:
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RecursiveFind {
    public static int findLastIndexOf(int start, int end, String pattern,
            String haystack) {
        return findLastIndexOf(start, end,
                Pattern.compile(pattern).matcher(haystack));
    }

    private static int findLastIndexOf(int start, int end, Matcher matcher) {
        int pivot = ((end - start) / 2) + start;
        if (matcher.find(pivot)) {
            // recurse on right side
            int foundIndex = findLastIndexOfRecurse(end, matcher);
            if (foundIndex != -1) {
                return foundIndex; // match found on right side
            }
        }

        if (matcher.find(start)) {
            // recurse on left side
            int foundIndex = findLastIndexOfRecurse(end, matcher);
            if (foundIndex != -1) {
                return foundIndex; // match found on left side
            }
        }

        // not found at all between start and end
        return -1;
    }

    private static int findLastIndexOfRecurse(int end, Matcher m) {
        int foundIndex = m.start();
        if (foundIndex > end) {
            return -1;
        }
        int recurseIndex = findLastIndexOf(foundIndex + 1, end, m);
        if (recurseIndex == -1) {
            return foundIndex;
        } else {
            return recurseIndex;
        }
    }
}

Sunday, July 3, 2011

Actions in the NetBeans Platform: A major shortfall

The NetBeans Platform is a powerful Rapid Application Development tool.  It provides a solid framework for loose-coupling via the Lookup class and it comes with a robust modular development environment where dependencies must be explicit and well-defined.  In addition, its GUI Builder drastically reduces time spent designing Swing components while the Window System provides some pretty awesome standard features, such as tabs, drag-and-drop window placement, and individual window min-/maximization.

However there is a major shortcoming in the platform.  This problem is not a bug or an implementation issue (although there are certainly plenty of those in the platform), rather it is a glaring design problem which is unforgivably inconsistent with the dev-team's dual-mantras of loose-coupling and modular development.  I'm talking about their actions paradigm.

Let's say you that want to create an action that will open a new TopComponent when you double click on a ProductNode.  According to every tutorial/example about actions that I've come across, you implement such an action like so:

package com.potetm.actions;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import org.openide.awt.ActionRegistration;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionID;
import org.openide.util.NbBundle.Messages;

@ActionID(category = "File", id = "com.potetm.actions.OpenWindowAction")
@ActionRegistration(displayName = "#CTL_OpenWindowAction")
@ActionReferences({
    @ActionReference(path = "Toolbars/File", position = 0)
})
@Messages("CTL_OpenWindowAction="Open Window")
public final class OpenWindowAction implements ActionListener {

    public void actionPerformed(ActionEvent e) {
        WindowManager.getDefault().findTopComponent("OtherWindowTopComponent").open();
    }
}
You would then register this action by overriding the getPreferredAction() method in your ProductNode.

The problem with this implementation is that OpenWindowAction, which OtherWindowTopComponent neither knows about nor cares about, is now telling OtherWindowTopComponent when it should open.  Now, to be fair, while this is never ideal, the current OpenWindowAction action might suffice for this trivial example.  After all, it's calling a method common to all TopComponents meaning it doesn't know anything at all about this particular TopComponent.  Not only that, but it doesn't even have to explicitly depend on OtherWindowTopComponent.class due to the fact that WindowManger.findTopComponent(...) only takes a string.  (Some might argue that that is, in itself, a problem, but for the sake of argument, I'll list it as an advantage.)

However, this whole line of reasoning falls apart as soon as you want an action to do anything more complicated than simply opening a window.  Suppose, for example, that you also want this newly opened window to display detailed information about ProductNode's Product.  The easiest solution under the current paradigm is to create an OtherWindowTopComponent.setProduct(Product) method, which is essentially what is recommended in The NetBeans Platform 6.9 Developer's Guide.  (Scroll down to the section on "Creating Global Actions".)  Now your actionPerformed(...) method looks like this:
public void actionPerformed(ActionEvent e) {
    Product product = ((Node) e.getSource()).getLookup().lookup(Product.class);
    OtherWindowTopComponent otherWindowTopComponent =
        (OtherWindowTopComponent) WindowManager.getDefault().findTopComponent("OtherWindowTopComponent");
    otherWindowTopComponent.open();
    otherWindowTopComponent.setProduct(product);
} 
Now that's significantly more intrusive, and yet this example is still relatively trivial.  It's not difficult to see how an action which requires many different objects working in tandem would turn into a God Object in every sense of the term.

I found this truly incredible. Especially considering the fact that every tutorial, video, and how-to on the merits of the NetBeans Platform includes a lengthy discussion on loose coupling and modularity. It is undoubtedly true that these two attributes lead to robust, easily maintainable code. The tragic thing is that actions in NetBeans are massive violations of those principles. They violate the principles of modularity because any module that contains actions could potentially be forced to depend on every other module due soley to the action class. Even if you put every action in the application into a single module (which is itself a poor idea), that single module would inevitably depend on every other module for one reason or another. While this is allowed in the NetBeans Platform (as long as no module depended on the actions module), it is a truly terrible idea. It's one thing to have every module in an application depend on a single module. That just means that that module provides a particular service which every other module happens to need. However, if the roles were reversed, if one module were to depend on every other, that would mean that there were no clear relationships between that module and the others. It would seem (and would indeed be true) that that module just started depending on other modules willy-nilly whenever it was convenient.

NetBeans actions' violation of the principles of loose-coupling is even more severe. The loose-coupling paradigm states that each class should explicitly depend on as few other classes as possible. More specifically, as it applies to the NetBeans Platform, that means that you use Lookups to transfer information from one class to another instead of explicitly calling a particular method in another class. The act of changing a Lookup notifies any interested parties of the change without either party explicitly knowing anything about the other. You could, for example, take any TopComponent out of the application and it would still run, just without the functionality that the missing TopComponent provided. The same is not true for actions. An action is notified of an event, and then starts explicitly calling methods on every other class that it needs to complete its action. If you take any TopComponent that it was using out of the application, not only would the action be broken, it wouldn't compile.

This poor programming structure is further exacerbated by the fact that NetBeans manages the lifecycles of the actions which it creates and their lifespans are extremely short. If it were possible to manually manage the lifecycle of an action, you could instantiate it on application start and immediately set up an observer pattern, with interested parties being notified by the action when a hotkey or button is pressed. Unfortunately, given the circumstances I have been forced to hack my way to good programming practice.

My solution was to set up an observer pattern with a class that can be looked up via the @ServiceProvider annotation. The NetBeans-managed action would then notify this class when an action has occured, which would in turn message every party signed up to be notified. See the diagram below:



The two classes in the dotted-box are essentially two objects doing the job of one. The ActionProvider serves as the "observable action" for the application. It will inform interested parties when a hotkey/button has been pressed. It in turn is informed by the ActionDelegate, which is instantiated and managed by the NetBeans Platform. ActionDelegate also has all of the annotations necessary to make the action show up in menus, be called for hotkeys, etc.

I actually simplified the whole operation by making an AbstractActionDelegate and an AbstractActionProvider which do all the work for every action. The AbstractActionDelegate uses reflection to look up its corresponding ActionProvider. I'm not a huge fan of reflection, however this also enforces a naming convention. I also made the actionPerformed(...) method on both classes protected so that I could pass on the original ActionEvent from the NetBeans Platform if necessary*.

I plan on uploading the code for those classes to my website pretty soon. I'll update this post with a link when I do.

------------------------------------------------------------------------------------------

*Ordinarily you want to make an ActionEvent's source object be the ActionProvider from which it came. This is so that your
ActionListeners can distinguish between actions (because you don't know what object NetBeans will list as the event source). However, especially in the case of actions triggered by Nodes, you need the Node to be the event source because the node contains the object you want in its lookup.


EDIT:  I finally uploaded the source code to github.

Saturday, June 18, 2011

Spring/Hibernate/JPA and Transactions

I spent much of the day yesterday researching how transactions are handled under Spring 3.0.x with JPA and Hibernate 3.6.x handling persistence.  I thought I would take some time to write down what I learned.

We originally made it standard practice to annotate both the service and repository layers with Spring @Transactional annotations.  For example:

Here's the repository layer:

// *HINT* This is incorrect.  It will compile but will probably not behave as you expect
@Repository
class ProductDaoImpl {
  @Autowired
  EntityManager entityManager;

    @Transactional(readOnly = true)
    public Product findProductById(String id) {
        ...
    }

    @Transactional(readOnly = false)
    public void saveProduct(Product product) {
        entityManager.merge(product);
    }
}
And the service layer
@Service
class ProductManagerImpl {

    @Autowired
    ProductDao productDao;

    @Transactional(readOnly = true)
    public Product findProductById(String id) {
        productDao.findProductById(id);
    }

    @Transactional(readOnly = false) {
    public void saveProduct(Product product) {
        productDao.saveProduct(product);
    }
}
In order to test transactions in the system we did something like this in the repository layer:
@Repository
class ProductDaoImpl {
  @Autowired
  EntityManager entityManager;

    @Transactional(readOnly = true)
    public Product findProductById(String id) {
        ...
    }

    @Transactional(readOnly = true)
    public void saveProduct(Product product) {
        ...
    }
} 

While leaving the service layer unchanged.

Our thinking was one of two things would happen: 1) the Service layer would start a read-write transaction, hit the read-only demarcation in the repository layer, and start a new read-only transaction, or 2) Spring would figure out that a read-only transaction was needed and make the whole interaction read-only.

Imagine our surprise when we found our changes persisted to the database without complaint.

It turns out that when you start a transaction the first thing that happens is the system checks to see if there's already a transaction open that it can piggyback on.  So when the system opens a read/write transaction then tries to start a new transaction in the dao, it finds the already opened transaction, piggybacks on it, thereby allowing the dao to write to the database.

So it turns out to be better practice to put all of your @Transactional annotation on the service layer.  This eliminates any ambiguity as to whether or not an operation will be read-only.

However, even after moving all of our annotations to the service layer, we were still surprised to find that we received no exceptions when we called merge in a transaction marked as read-only.  The system would quietly fail with no notification whatsoever.

After some digging around I found that Spring-managed transactions don't actually enforce read/write permissions.  Instead it delegates enforcement to the database and to Hibernate.  (Well that's the rumor anyways.  I never actually saw any proof that Spring informed either the database--PostgreSQL in my case--or the JDBC driver that the transaction was read-only.)  And since Hibernate has no notion of a read-only transaction, it does the next-best thing by setting the flushmode to FlushMode.MANUAL.  Luckily the Hibernate implementation of Transaction.commit() won't flush if the flushmode is manual.  That turns out to be the only real check on the read-only transactions.  So it is possible write to the database by calling EntityManager.flush() before the transaction closes.

So, in short:
1) Put all of your @Transactional annotations on the service layer to eliminate ambiguity.
2) Don't depend on a @Transactional(readonly = true) demarcation to actually be read-only.  You have to make certain that the EntityManager isn't flushed during the transaction because that will indeed persist changes.