Clone this wiki locally

For background information on extensions in NetLogo, see the Extensions section of the User Manual.

Several sample extensions are included with NetLogo. The full Java (or Scala) source code for all of them is hosted on GitHub. Most are in the public domain. Some are copyrighted, but under an open-source license.

Many extensions developed by users are available for download from the Extensions page. Most of them include source code.

To discuss NetLogo development, including usage of NetLogo APIs, browse or join the netlogo-devel group.

Writing Extensions

This page introduces this facility for Java programmers. We'll assume that you know the Java language and related tools and practices.

Our API's are also usable from other languages for the Java Virtual Machine, such as Scala. Following the Java information is a section on how to write an extension in Scala.

Summary

A NetLogo extension consists of a folder with the following contents:

Required:

A JAR file with the same name as the extension, the following contents:

one or more classes that implementat org.nlogo.api.Primitive

a main class that implements org.nlogo.api.ClassManager

a NetLogo extension manifest file, with the following four tags:

Manifest-Version, always 1.0

Extension-Name, the name of the extension.

Class-Manager, the fully-qualified name of a class implementing org.nlogo.api.ClassManager.

NetLogo-Extension-API-Version, the version of NetLogo Extension API for which this JAR is intended. If a user opens the extension with NetLogo that has a different Extension API version, a warning message is issued. To tell which version of the Extension API your NetLogo supports, choose the "About NetLogo" item in the "Help" menu and then click on the System tab. Or, you can launch NetLogo.jar with the --extension-api-version argument.

Optional:

If you want the extension to work in applets, .jar.pack.gz versions of the main JAR and all supporting JARs, compressed with Pack200

One or more additional JAR files which the extension requires.

A lib directory with any required native libraries.

One or more NetLogo models demonstrating how the extension is used.

A src directory containing the source code for the model

Documentation.

To build your extension, you must include NetLogo.jar in your class path. In addition, the lib directory (also from the NetLogo distribution) must be in same location as NetLogo.jar; it contains additional libraries used by NetLogo.jar.

Tutorial

Let's write an extension that provides a single reporter called first-n-integers.

first-n-integers will take a single numeric input n and report a list of the integers 0 through n - 1. (Of course, you could easily do this just in NetLogo; it's only an example.)

1. Create extension folder

Since an extension is a folder with several items, we first need to create our folder. In this example, it is called example. We will be doing all of our work in that folder. We will also want to create a src sub-folder to hold our Java code, and a classes sub-folder for the compiled classes.

2. Write primitives

The primitives are implemented as one or more Java classes. The .java files for these classes should be put in the src sub-folder.

A command performs an action; a reporter reports a value. To create a new command or reporter, create a class that implements the interface org.nlogo.api.Command or org.nlogo.api.Reporter, which extend org.nlogo.api.Primitive. In most cases, you can extend the abstract class org.nlogo.api.DefaultReporter or org.nlogo.api.DefaultCommand.

The number objects we put in the list are Doubles, not Integers. All numbers used as NetLogo values must be of type Double, even if they happen to have no fractional part.

To access arguments, use org.nlogo.api.Argument's typesafe helper methods, such as getDoubleValue().

Throw org.nlogo.api.ExtensionException to signal a NetLogo runtime error to the modeler.

A Command is just like a Reporter, except that reporters implement Object report(...) while commands implement void perform(...).

2. Write a ClassManager

Each extension must include, in addition to any number of command and reporter classes, a class that implements the interface org.nlogo.api.ClassManager. The ClassManager tells NetLogo which primitives are part of this extension. In simple cases, extend the abstract class org.nlogo.api.DefaultClassManager, which provides empty implementations of the methods from ClassManager that you aren't likely to need.

addPrimitive() tells NetLogo that our reporter exists and what its name is.

3. Write a Manifest

The extension must also include a manifest. The manifest is a text file which tells NetLogo the name of the extension and the location of the ClassManager.

The manifest must contain three tags:

Extension-Name, the name of the extension.

Class-Manager, the fully-qualified name of a class implementing org.nlogo.api.ClassManager.

NetLogo-Extension-API-Version, the version of NetLogo Extension API for which this JAR is intended. If a user opens the extension with NetLogo that has a different Extension API version, a warning message is issued. To tell which version of the Extension API your NetLogo supports, choose the "About NetLogo" item in the "Help" menu. Or, you can launch the NetLogo.jar with the --extension-api-version argument.

Note that the API version is rarely the same as the NetLogo version. For example, all of the releases in the NetLogo 5.x series have the same API version, namely 5.0.

Mostly this is a straightforward, line-by-line translation of the Java version.

One difference is worth noting. In the Java version, we explicitly converted ints to Double objects. As previously mentioned, all numbers used as NetLogo values must be of type Double, even if they happen to have no fractional part. In the Scala version we leverage implicit conversions to do this work for us. We do so by importing org.nlogo.api.ScalaConversions._, which provides us with two new methods via implicit conversions. The first is toLogoList, which converts Scala Seqs to LogoLists as seen in: (0 until n).toLogoList. The second is toLogoObject, which converts any supported Scala value to the appropriate NetLogo type. The conversions provided by toLogoObject are:

The conversions to LogoList are recursive. Nested collections in the input will be converted to nested LogoLists in which all elements have been converted by toLogoObject. ExtensionObjects, on the other hand, are not recursed into.

Using the toLogoObject conversion is simple. Just call the method on an an Any. Example: 7.toLogoObject

3. Create a JAR

To create an extension's JAR file, first compile your classes as usual, either from the command line or using an IDE.

Important: As when compiling Java, you must add NetLogo.jar (from the NetLogo distribution) to your classpath when compiling.

Here's an example of how compiling your extension might look from the command line:

You will need to change the classpath argument to point to the NetLogo.jar file from your NetLogo installation. This command line will compile the .java and put the .class files in the classes subfolder.

Then create a JAR containing the resulting class files and the manifest exactly as was done with the Java classes. For example:

$ jar cvfm example-scala.jar manifest.txt -C classes .

4. Use your extension in a model

Using a Scala extension is the same as using a Java extension. However there is one caveat: NetLogo ships with a stripped down version of scala-library.jar. While most common classes (Array, List, Map) are present, it may be best to check, especially if your extension makes use of less common classes.

To check which classes are present in the scala-library.jar that ships with NetLogo, in the lib directory inside the NetLogo directory type this at the command line:

$ jar tf scala-library.jar

If you find that a class used by your extension is missing (either by checking manually or via a ClassNotFound exception), there is still hope. Place a copy of a full version of scala-library.jar into the root of your extensions directory (in this case example-scala). Or, since the full scala-library.jar is large (over 4 megabytes), you may wish to prepare a smaller jar containing only the specific missing classes you need to supply.

Extension development tips

Instantiation

Your class manager is instantiated in a fresh JVM classloader at the time a model using the extension is loaded.

This is done so that extensions are unloadable, so that when you open a new model, the extensions used by the previous model can be unloaded and the memory they used reclaimed. (The JVM does not allow unloading particular classes; you can only unload an entire classloader at once.)

Classpath

Don't forget to include NetLogo.jar in your class path when compiling. This is the most common mistake made by new extension authors. (If the compiler can't find NetLogo.jar, you'll get error messages about classes in the org.nlogo.api package not being found. If the lib directory isn't in the same location as NetLogo.jar, you'll get errors about other classes not being found.)

Supporting old Java versions

NetLogo works with Java 6 and later. If you want your extension to be usable by all (or even most) NetLogo users, your extension should support Java 6.

The easiest way is to accomplish this is do all your development with the Java 6 JDK.

It's also possible to develop for Java 6 using the Java 7 or later compiler, but you need to do two things:

Use the -source 1.6 -target 1.6 options to javac (or equivalent in your IDE) to tell the newer compiler to emit class files that are compatible with the older Java versions. This ensures that your code doesn't use any Java 7-or-later-only Java language features.

Use the -bootclasspath option to javac (or IDE equivalent) to compile against the Java 6 class libraries. (Note that this requires installing Java 6 anyway.) This ensures that your code doesn't make any Java-7-or-later-only Java API calls.

If you don't use -target 1.6, the usual result at runtime is a java.lang.UnsupportedClassVersionError with message “Unsupported major.minor version”.

Debugging extensions

There are special NetLogo primitives to help you as you develop and debug your extension. These are considered experimental and may be changed at a later date. (That's why they have underscores in their name.)

__reload-extensions forces NetLogo to reload all extensions the next time you compile your model. Without this command, changes in your extension JAR will not take effect until you open a model or restart NetLogo.

Language Tests

You can run language test from within your extension's sbt session. The NW-Extension uses this. See its build.sbt for an example.

Benchmarking

Similarly, you can run benchmarks from within your extension's sbt session. If you setup language tests for the extension, then just put your benchmark models in the models/test/benchmarks subfolder of your extension's root folder. Then you can run them with:

test:run-main org.nlogo.headless.HeadlessBenchmarker BenchmarkName

Third party JARs

If your extension depends on code stored in a separate JAR, copy the extra JARs into the extension's directory. Whenever an extension is imported, NetLogo makes all the JARs in its folder available to the extension.

If you plan to distribute your extension to other NetLogo users, make sure to provide installation instructions.

Applet support

But if you want your extension to work in applets, compile it using NetLogoLite.jar instead of NetLogo.jar, to be sure you are only referencing classes and methods that are available in the applet jar.

To keep the size of NetLogoLite.jar down, we use ProGuard to aggressively strip out unreferenced classes and methods. If ProGuard is removing something that your extension needs, let us know.

You'll need to run your extension's main JAR, and any supporting JARs too, through Pack200 to produce compressed .jar.pack.gz versions that are much smaller and therefore load much faster than plain JARs. In theory including the packed jars should be optional, but we've found that in practice, without them applets won't work on some web servers. Here's an example command line for running the pack200 tool:

If you are with comfortable with building NetLogo yourself, you can also experiment with adding stuff to the project/proguard/lite.txt file to change what is included in NetLogoLite.jar (see the ProGuard documentation). We are trying to keep the size of that JAR as small as possible, but open to the idea of adding stuff that really should be there.

For debugging applets, the Java Console can be very useful: it will allow you to see exceptions that are raised by your code (java.lang.NoSuchMethodError exceptions are usually a sign of trying to use something that was stripped away by ProGuard).

Extensions written in Scala

If your extension is written in Scala, you may not be able to compile against the applet JAR, because we use ProGuard to strip ScalaSig attributes from that JAR, to save space. What this typically causes to fail is implicit conversions, such as the ones in ScalaConversions and LogoList, since the fact that a method is implicit is stored in the ScalaSig attribute. If you hit this problem, either compile against the regular JAR instead, or explicitly call the implicit methods by name.

Even if you extension does compile, it might still fail at runtime. One reason for that is because ProGuard also strips away parts of the Scala library that NetLogo does not use, but when you compile your extension, you compile it against the full Scala library, so you get no compile-time errors.

And it is not always obvious: some things involving reflection do not work. Structural types use reflection under the hood and are amongst the things that do not work. A pattern like this involves structural types:

valy=newX { defsomeNewMethod= () }

This one can usually be replaced by something like:

objectyextendsX { defsomeNewMethod= () }

You might also find other patterns like this. Again, if that is the case, let us know.

Documenting your extension

Note that there is no way for the modeler to get a list of commands and reporters provided by an extension, so it's important that you provide adequate documentation.

Conclusion

The extensions facility is not yet complete. The API doesn't include everything you might expect to be present. Some facilities exist but are not yet documented. If you don't see a capability you want, please let us know. Do not hesitate to contact us with questions, as we may be able to find a workaround or provide additional guidance where our documentation is thin.

Hearing from users of this API will also allow us to appropriately focus our efforts for future releases. We are committed to making NetLogo flexible and extensible, and we very much welcome your feedback.

First, navigate to the extension that you want to download on GitHub. Download the repository as a ZIP file and unzip it.
If you wish to modify the code, open the /src directory and modify the text files inside using your text editor or IDE of choice.

Now you must add the sbt folder to your system path. This is so that when you tell the computer to run the program called "sbt," it knows where to find the program you're looking for. The sbt directory will probably be something like C:\Program Files (x86)\sbt. You can look up instructions for modifying your system path online. One way to do it is to navigate to System under the Control Panel, select "Advanced System Settings" on the left, select "Environmental Variables" in the "Advanced" tab, select "PATH" under "System Variables", and select "Edit." Then, add a semicolon at the end of the long text, and copy-paste the directory (C:\Program Files (x86)\sbt or similar).

While you're in \sbt, you may want to run sbt.jar and sbt.bat. This step may or may not do anything.

Finally, download Git from http://git-scm.com/download/win, and add the directory containing git.exe (C:\Program Files (x86)\Git\bin or similar) to your system path.

You are now prepared to build the extension. Open the Command Prompt (search for "cmd" in the Start Menu). Enter the command "cd [directory]" to navigate to the extension (for example, "cd C:\GoGo Extension"). Then enter "sbt package." Your code should compile at this time. If there are errors in your code, the command prompt will output error messages.

You should end up with a .jar file in the extension directory. Copy this .jar file to the appropriate directory in NetLogo (e.g. C:\Program Files (x86)\NetLogo 5.0.5\extensions\gogo). The next time you run NetLogo, you should have the new version of the extension.