I'm starting the process of packaging a Java-based application for
MacOS, and I'm wondering what the "preferred" way of organizing
jars, resources, etc. would be if you have more than just a
standalone application bundle. In my case, the application includes
some network services that run out of the same jars as the
application itself.
It depends.
Different audiences might be better served with an arrangement suited
to their needs and experience level. So it depends on your audience.
If your app depends on (i.e. requires) the network services, then
bundling into a single integrated whole might be best. If your app
doesn't depend on the services, i.e. it can run without the services
active, then splitting them up might be best. If some users might
use your app but not the services, or if the services and the app are
aimed at different audiences, then completely separate structures
(e.g. 2 or more distinct apps or launchables) might be best.
If your services can be run completely separate from your app, then
you should make them completely separable. That is, if there's a
reason why a user might run your services but never run your app,
then that should be possible to do. If the services and app are
separable, then the user should even be able to remove the app
(MyApp.app) entirely, but still keep the services.
If the services can run per-user (i.e. as launch-agents instead of
launch-daemons), you might consider a completely different placement
for the services.
So briefly, it depends on your audience, on the relationship betwee
your app and services, and the usage patterns of your audience for
the app and services.
My options would seem to be:
1) Install everything into /Applications/MyApp. Thus I'd have /
Applications/MyApp/MyApp.app, /Applications/MyApp/lib/
wholebunchofjars.jar, etc. The service configurations would go in /
Library/LaunchDaemons. Upside: if the user moves the .app folder,
things will still run, since the app and services will know to look
in /Applications/MyApp/lib.
Exploit the structure of app-bundles.
First, /Applications/MyApp/MyApp.app would force users to have a
hierarchical menu for your app. They might not want that.
Second, /Applications/MyApp/lib/wholebunchofjars.jar is gonna confuse
all the users who have no idea that the lib folder next to MyApp.app
is required to be there. And all the users who do know what it's for
are gonna think it's sloppy or uninformed to slap that folder there
when it could be perfectly well located inside the app-bundle.
That's why an app-bundle is a self-contained directory tree: so it
can be moved without leaving half its internal organs behind.
Third, if a user moves /Applications/MyApp/MyApp.app elsewhere, it's
unlikely they will leave /Applications/MyApp/lib in place. The most
logical reason for moving an app is to get it entirely out of its
original location, so deleting /Applications/MyApp/lib is the most
likely second step after moving the app. That will cause grave
disorder in your launch daemon plists. Either embed the lib inside
the app-bundle, or put it in a more stable location that users are
unlikely to clean out.
Fourth, users might not want to put the app in /Applications. For
example, there might be restrictions on that folder in a shared
environment, or company policies against it, or just personal policy
(like me). I never intentionally add apps to /Applications, and it
really irks me when some app can ONLY be installed there.
2) Include everything except the launchd plist files in /
Applications/ MyApp.app. This looks neater, but if the user moves
the app bundle, the services will no longer run.
Agreed. This would be very bad. Don't do it.
3) Create a framework in /Library/Frameworks/MyApp.framework, and
put all the libraries in there. Services and app will all look for
their jars in the framework directory, and I can even version
things if I want.
You can version things anywhere you put them, not just in /Library/
Frameworks/. There's no magic versioning you get by placing things
in /Library/Frameworks/.
Also, you can't version things arbitrarily anyway if your services
are running as a launch daemon. You have to stop the job, terminate
the daemon, change the jar (versioned or not), then start the job
again. Because it's a launch daemon, all that has to be done as root.
You also have to secure all the resources (jars, executables, etc)
used by the launch daemon, so they can't be altered by anyone except
root. I don't know what your experience in this area is, but it's
not as simple as it might seem. If it's not necessary to run your
services as root, then you should use an unprivileged launch agent
instead.
With no other information about your app or services, I think Doug
Zwick's suggestion is the best: use /Library/Application Support/
MyApp/. If you're running your services as root, you will still need
to lock down all the resources used by the privileged launch daemon,
including the path of parent dirs used to reach the resources. This
is one reason why it's usually best to make daemons as self-contained
as possible, even if it means replicating files for their exclusive
use. Also remember that Unix has hard-links, and sometimes a hard-
link isn't a security risk (NB. hard-link != symlink in this regard).
-- GG
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Java-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/java-dev/email@hidden