Registering/running tasks

Apache NetBeans Wiki Index

Note: These pages are being reviewed.

The last thing to do with a correctly implemented task is to let it really run. There are two basic ways how to do it. First, register it into the infrastructure so that it will be run automatically when the source gets modified. Second, running it directly.

Use the former option if:

  • You need to react to changes of document in the editor

  • You need to react to changes in caret position in the editor

  • You want to do something with files which are collected in some existing lookup

  • You need to run a task on arbitrary file/set of files every time a file changes

Use the later option:

Registering tasks using the factories

There are support classes for the most used cases of repeatingly running tasks. The classes are in the org.netbeans.java.source.support package. Generally you need to subclass the factory of your choice (see later) and implement the abstract methods or override some methods. You will need to implement the getPhase() and getPriority() methods and return an enum constant of your choice in order to indicate at which javac phase and with which priority the tasks created by this factory should run. (See above for discussion about phases and priorities). The most important method to implement is createTask( FileObject ), which has to return the task to be run.

Once you have your factory implemented you will need to register it into the global Lookup. To do so create a folder called META-INF.services in your project and put a file called org.netbeans.java.source.JavaSourceTaskFactory (note: has this changed to org.netbeans.api.java.source.JavaSourceTaskFactory?) in the folder. In this file list the fully qualified names (one per line) of all factories you want to register. So if you want to register two factories the file content would look like:

foo.bar.my.java.tasks.MyEdtiorAwareTaskFactory
foo.bar.my.java.tasks.MyCaretAwareTaskFactory
  • Reacting to changes in the editor

    Is easy. Subclass EditorAwareJavaSourceTaskFactory and implement all abstract classes. Your class could look like:

    public class JavaSourceTaskFactoryImpl extends EditorAwareJavaSourceTaskFactory {
    
        public CancellableTask<CompilationInfo> createTask(FileObject file) {
            return new MyTask();
        }
    
        public Priority getPriority() {
            return Priority.LOW;
        }
    
        public Phase getPhase() {
            return Phase.RESOLVED;
        }
    
    }

    The run( CompilationInfo ) of your task will then be run every time a file changes in the editor and the compiler gets into the state where all identifiers are resolved.

  • Reacting to a caret position change

    Do the same thing as in the previous paragraph; just make sure you extend CarretAwareJavaSourceTaskFactory

  • Tracking changes of files in a lookup

    This might sound like a strange thing to do, but in NetBeans there are often lookups available which contain interesting files. For instance the Java navigator component can be written this way. You extend the LookupBasedJavaSourceTaskFactory you call the setLookup(Lookup) method on it pointing it to the proper lookup. The rest is identical to steps described in the first bullet point. Now when any of the files in the lookup changes the task you created for it will run. Should you want to ignore some of the files override the getFiles() method and do the filtering in it.

  • Reacting to changes in an arbitrary set of files

    If you think you need this, think again. Maybe you don’t. If you still think you do subclass the JavaSourceTaskfactorySupport class. Implement the getFiles method so that it will return the FileObjects you are interested. If the set of files is not fixed call fireChangeEvent() every time the set of files changes. Follow the first bullet point to implement all other abstract methods.