Build small things that fit well together and you will sleep better than the team that built one giant thing that fits nowhere.
A rainy Tuesday and a stubborn monolith
The coffee went cold while the stack traces kept growing. That was the whole vibe of the morning. One Swing app, one monster jar, and a tangle of static singletons with opinions about everything. Each change pulled three threads somewhere else. We had a serious case of the all in one jar blues.
I kept thinking about the NetBeans Platform. Not the IDE, the actual platform. It ships as a set of modules and a harness for building desktop apps that are modular from day one. You get a window system, actions, an update center, a clean way to wire features with Lookup, and packaging that does not make you cry on release day. It is not flashy. It is steady. That sounded perfect.
Since this week brought a fresh NetBeans 7.2 build with performance boosts and smoother code completion for Java, the timing felt right. I opened the IDE, hit New Project, chose NetBeans Platform Application, named it, and landed on a structure that already felt saner than our jar mountain. The app launched with a welcome screen, a main window, and menus. No ceremony. Just a running shell waiting for features to drop in as modules. That is the appeal: pick the bits you need, keep the rest out.
Finding a home on the NetBeans Platform
Plenty of folks ask why pick this over writing plain Swing. My answer is simple. Modularity forces discipline. On the platform, every feature becomes a module with clear dependencies and public packages. You cannot just reach into your neighbor’s internals. You surface contracts and keep the rest private. That alone pays for itself the first time you refactor without breaking the world.
There is also the toolbox you get for free. The Window System handles docking and persistence. The Actions system wires menu and toolbar items to context. The Nodes API and Explorer views give you tree and table views that react to selections and lookup without new plumbing each time. Throw in the Visual Library for diagrams, the Autoupdate client for upgrades, and installers that work across platforms, and you have something that feels like rails for desktop.
Today also feels like a good moment for desktop apps in general. Java 7 has been out for a while, and NetBeans speaks it fluently. JavaFX 2 is growing up and can live inside a Swing app. Teams are moving from Subversion to Git, which NetBeans handles nicely. The pieces around the editor are lining up, and the platform sits in that sweet spot where you want structure without ceremony.
Deep dive 1: Modules and the NetBeans Lookup
Let’s start with the backbone. A NetBeans module is a jar with metadata that states its code name, version, and dependencies. You pick which packages are public. Only those are visible to other modules. Everything else stays private by default. This is not just policy. The runtime enforces it. That boundary lets teams ship features without turning every class into public API by accident.
Now to the glue. The Lookup pattern is the platform’s way to say do not hardcode references. Instead, publish services to a lookup and find them by type. This sounds abstract until it saves you. Imagine a report module that needs data. Do not import a data module directly. Ask the lookup for a ReportDataProvider and let any module supply it. Later you can replace the provider without touching the report code. That is loose coupling you can feel on release week.
Lookup lives in two flavors. One is global, reflecting the current selection or context inside the app. The other is local to a component. You can put objects into a component’s lookup and any action or panel will react to them when that component is active. This is how menus enable and disable themselves based on what the user clicked. No wiring spaghetti. The runtime already knows the active component and merges its lookup into the global context.
A few practical tips:
- Define clear module APIs. Keep implementation in friend packages or private packages. Be strict early.
- Use Lookup and Service Provider registrations to keep dependencies pointing at interfaces, not at classes.
- Split features by feature, not by layer. A feature module that owns UI plus logic stays easier to reason about.
- Group modules into clusters for packaging and updates. Core, features, and extras is a simple starting split.
There is a lot of talk about OSGi this year. The NetBeans module system is not OSGi. The platform chose a simpler model that matches Swing apps well and gives you runtime classloader boundaries with versioned modules. If you need pure OSGi for other reasons, that is a different road. If you want sane modules in a Swing desktop app today, this road is solid.
Deep dive 2: UI on rails with Window System, Nodes and Actions
The Window System is where your app starts feeling professional. You create components that dock, slide, and persist size and position across restarts. The runtime takes care of restoring them. If the user drags a view to a second monitor, it stays there next time. That is a small thing that users love.
The best part is how views talk to actions. Every action can declare the type of object it needs in lookup. When the user selects something that matches, the action enables itself automatically. The menu item that says Export to CSV wakes up only when a table with data is active. You do not write enable logic across the app. You describe the need, and the system handles it. That makes new actions cheap to add and old actions safe to refactor.
For data heavy screens, the Nodes API and Explorer views keep things tidy. You wrap your domain objects in nodes that can expose children, properties, and actions. Explorer views like trees and tables render them with selection wired to lookup for free. It is a pattern that scales from a simple master detail to gnarled hierarchies without changing your app structure.
When you need diagrams or custom widgets, the Visual Library gives you anchors, routing, zooming, and a clean scene graph. You can build a graph editor or a process designer without reinventing scrolling and selection. For preferences, the Options API drops your panel into the standard Options dialog, with storage handled for you.
Branding is not an afterthought. The platform lets you brand the application name, splash, icons, and window layouts through resource overrides. You can ship white labeled builds or editions with different module sets. If you ever had to fork a codebase just to change a logo, this will feel like a breath of fresh air.
A few design notes that keep UIs clean on the platform:
- Let selection drive behavior. Put the interesting object into lookup and let actions react to it.
- Keep window components small. One reason per view. If a component starts knowing too much, split it.
- Prefer explorer views to hand built tables when you need selection aware lists. The wiring is already there.
- When embedding JavaFX inside Swing, isolate the bridge inside a module and expose only interfaces. That keeps options open.
Deep dive 3: Build, delivery and updates with Ant or Maven
Shipping beats not shipping. The NetBeans harness does the boring parts so you can ship with a clear head. Out of the box you get NBM artifacts per module, a branded application, and launchers for the major desktops. The build creates clusters, zips, and installers. You can add an Autoupdate Center so the app can fetch new modules on the fly. That means you fix a bug in one module, push it to your update server, and users pull it without reinstalling the app.
There are two roads for builds. The older one uses Ant projects that the IDE manages. It is simple and battle tested. The newer road uses Maven with packaging types for modules and applications. If your team already lives in Maven, the platform plays along. Each module is a Maven project, versions are regular Maven versions, and you can plug the suite into continuous integration with Jenkins. Both roads produce the same kind of artifacts and both support update centers.
Versioning matters when modules depend on each other. Bump versions in a way that tells the truth about compatibility. Keep module spec versions stable for bug fix releases and move them forward when you change APIs. The platform can enforce version ranges so you do not accidentally load a module that needs a newer API than you shipped.
Third party libraries are easy to wrap. The IDE can create a library wrapper module that exposes only the packages you want to be visible. This avoids classpath leaks and lets you upgrade a library without touching unrelated modules. For native launch concerns, you can ship custom JVM options and memory settings per platform through branding, all generated by the harness.
Here is a simple release checklist that keeps teams calm:
- Freeze APIs and mark modules with the right spec version.
- Run the app with clean userdir to catch migration issues early.
- Sign NBMs if your update center is public or used behind strict desktops.
- Prepare a staging update center and point a QA build to it first.
- Measure startup with profiling turned off to see real user timing.
If you like to automate, the Ant harness and the Maven plugin both expose targets for branding, installers, and updates. Wire that into Jenkins and you can tag, build, and publish modules to your update center from one job. That keeps release day from turning into a ritual with five manual steps and two lucky charms.
SEO quick hits: NetBeans Platform, modular applications, Java desktop, RCP, Lookup API, Nodes API, Explorer views, Window System, Visual Library, Maven NetBeans, Autoupdate Center, Swing, JavaFX. If you landed here searching for a cleaner way to build a Java desktop app, you are in the right place.
Reflective close: Build small, ship often, keep sleeping
I still like web apps for many things, but there are moments when a desktop app feels right. When you need heavy data on the client, a fast UI, and deep keyboard work, Swing is still a solid friend. The NetBeans Platform gives that friend a proper house. It keeps pieces small, encourages clean boundaries, and takes care of plumbing you do not want to touch every sprint.
Eclipse RCP has a strong following and OSGi is a fine model in its domain. The NetBeans way focuses on essentials and keeps the learning curve steady. In practice, teams that start with a clear module plan, lean on Lookup, and let the Window System drive UI composition tend to ship without drama. The update center turns maintenance into a routine instead of a fire drill.
What I like most is the feeling that the platform will not surprise me at two in the morning. It is predictable. When a module misbehaves, I can disable it. When a feature grows, I can split it. When a customer asks for a custom build, I can brand it and flip modules on or off without touching code. That is the kind of control that keeps projects healthy.
If your current desktop app feels like a brick with buttons, try moving one feature onto the platform and see how it feels. Start with a module that has clear edges. Expose only what others need. Put your service into Lookup. Wire an action and a window. Watch how the rest starts falling into place. That is the moment the rain stops and the coffee stays warm.