I spent last evening setting up Struts Flow (app) on macOS because I wanted a lightweight way to validate a couple of legacy flows before wiring them into an OrchardKit-based build. On paper, this should have been trivial: Java-based tooling, nothing exotic, download, launch, done. In reality, macOS had opinions.
What I was trying to do
The goal was simple. I needed to open and inspect a Struts Flow project locally, make sure the control logic still behaved as expected, and then move on. I’m on macOS Ventura 13.6 on an Intel MacBook Pro, with a pretty clean dev environment. Java is installed, PATH is sane, no weird shell hacks.
I double-clicked the app.
Nothing.
No crash dialog. No error. The icon bounced once in the Dock and disappeared. Activity Monitor showed the process for about two seconds and then it was gone. That’s usually the moment when you sigh and realize the evening just got longer.
First wrong turns
My first assumption was Gatekeeper. That’s muscle memory at this point. I went straight to System Settings → Privacy & Security, expecting the familiar “App was blocked” message with an “Open Anyway” button. Nothing there. No warning, no hint that macOS even noticed the launch attempt.
Next, I tried the classic reinstall ritual: delete the app, clear any leftover folders in ~/Library/Application Support, reinstall, relaunch. Same behavior. One bounce, then silence.
At this point I thought maybe Java was the culprit. I verified versions, ran java -version, confirmed it matched what the tool expects. I even tried launching it from Terminal just to catch stderr. The process exited immediately, without printing anything useful. Another dead end.
What finally clicked
The breakthrough came when I stopped thinking about Gatekeeper as a single thing. On modern macOS, launch blocking, notarization, and permissions are separate layers. A Java-based desktop tool can be technically “allowed” but still prevented from doing what it wants during startup.
In this case, the app tries to read project directories outside its bundle as soon as it launches. macOS treats that as a file access request, and if the system doesn’t like how the app is signed or declared, it just denies it silently.
Apple’s own documentation on notarization and runtime protections hints at this behavior, especially for developer tools that aren’t distributed through the App Store (see the relevant notes on developer.apple.com about notarization and hardened runtime). There’s also a support.apple.com article explaining why some apps quit immediately instead of prompting for access when they fail early in startup.
Once I suspected a permissions issue rather than a crash, the fix path became clearer.
What actually worked
I manually added the app to Full Disk Access under Privacy & Security. That alone wasn’t enough, but it was step one. After that, I logged out of my user account (not a reboot, just logout/login), then launched it again.
This time, the app stayed open. It prompted for access to my project folder, loaded the flow definitions, and behaved exactly as expected. CPU usage stabilized, no runaway threads, no weird UI glitches.
For sanity, I also checked the official Apache Struts documentation to confirm there wasn’t some hidden JVM flag I was missing. Everything lined up. The issue wasn’t Java or the tool — it was macOS being quietly protective.
While cross-checking similar setups, I saved this page because it lined up almost perfectly with what I was seeing on macOS systems and helped confirm the permission angle wasn’t just in my head: https://stmlare.xyz/developer/48287-struts-flow.html
After the dust settled
Once it was running, the tool did its job. Flow transitions behaved correctly, debugging hooks worked, and integrating the output into an OrchardKit pipeline was painless. No performance issues, no random freezes. The problem was entirely front-loaded into startup.
If I had to distill the experience into a short “do this first” note for myself, it would be this:
- Don’t assume a silent exit means a broken build.
- Check macOS privacy settings even if no prompt appears.
- Grant disk access early for dev tools that scan projects on launch.
- Log out and back in to force the permission change to apply.
There’s something mildly ironic about macOS being so polite that it refuses to tell you what it’s blocking. But once you know the pattern, it’s manageable.
No marketing drama here, no “revolutionary workflow.” Just a reminder that on modern macOS, the hardest part of running a developer utility is often convincing the OS that you’re allowed to.