Best practice for creating a desktop app using Java WebStart - java

Hope I can explain this clearly. I am creating a desktop application that has dependencies on other external jar files. For example, my application is Spring-based so there are some SpringFramework jar files that I will need in my application.
I am using Java WebStart to 'launch' this desktop application. (As to why I am doing this is that I need to execute this customised desktop application via the website that we are building).
However I ran into troubles when I executing my desktop application by clicking on the jnlp description file. It gives errors stating that there is no class definition for some of the classes that my desktop application is using. I then realise that my desktop application when packaged as a JAR file, it didnt include my other JAR dependencies with it. Hence the reason for the error.
I guess, I could include the external JAR dependencies in my desktop JAR file but this would make my desktop JAR file quite large. And this will be then make the download of my JAR file slow due to the large JAR file since clicking on the JNLP descriptor file will always source from the desktop JAR file from the server. (unless I can 'tell' the JNLP descriptor not to download if there is no new version on the server.)
Anyway, I was thinking if this is an acceptable approach where my desktop JAR file will not include the JAR dependencies but only references to it. When my desktop application launches, it will check if these dependencies are available on the desktop, and if it is not available, it will call another JNLP descriptor that will download the external JAR files and copy them to a pre-determined location that my desktop application references. Will this work? or is there a simpler solution to my problem?
thanks

The JNLP file should include references to both your main file but also all needed libraries. This is standard functionality and you should do it that way.
Note that you should have a time stamp in your file names to avoid cache problems when updating code.

You need to have your JNLP reference the additional jars you have. Yes this will take slightly longer to download, but as long as you are not including a bunch of jars that you don't need this should not take very long. Web Start is smart enough to not re-download jars that have not changed on subsequent start ups of the same application. I have Java Web Start applications that have several large jars and this works just fine.
As far as putting the extra jars on the user's machine, I would not advise this. If you are going to do that, then there is not much of a point to use Web Start and you might as well install the entire program on the desktop.

The other answers covered most bases, but just thought I should add that it might make sense to mark the extra Jars as download='lazy'.

Related

Java application installer for MacOS

I'm new at Java for Mac developement and I spent a lot of time finding a way how to create an installer. It's strange but it's not too much information about it. All the ways lead to using of JavaAppLauncher. (I use appbundler-1.0.jar and Ant to build .app) But I faced a following problem.
JavaAppLauncher sets working directory to user folder. My application consists of several jar files, resources and configuration files. All of them located in Contents/Java inside the .app structure. I use relative paths to them, relative to the executable jar with Main class.
I googled 2 discussions only, where someone asked how to set the working directory inside the .app bundle. Threre is a way to sed -Duser.dir JVM option in plist file of .app bundle. I tried this and it behaves strange. When I use "new File(".").getAbsolutePath()" - it shows the directory I pointed in -Duser.dir parameter, but when I try to create file on disk or read file from disk - it still goes to the user folder as it was by default.
May be someone knows what is wrong there?
Or is there any better way to create a java application bundle for Mac?
Thank you, guys.
Use JarSplice to create OS X app bundle. Compile all your jars and resources into one jar file and export as mac .app file.
Deploying Java Applications can be a pain if your application has multiple jars and native libraries. There are the options of using Java Web Start or Java Applets however these are not always suitable.
Executable Jars are an option, however if your project has multiple jars or native files then it can be tricky to use this option.
JarSplice attempts to solve this issue by allowing you to merge all your jars and native files into one, easy to use executable jar file.
Features:
Creates a single executable fat jar via an easy to use GUI.
Automatically extracts only the native files needed for the OS the jar is running on.
Automatically cleans up any extracted native files after the application quits.
Add VM arguments on jar creation which removes the need to enter them via the command line.
Optionally create a Shell Script (.sh) launcher for Linux with embedded fat jar.
Optionally create an OS X App Bundle (.app) for running your application.
Optionally create a Windows Application (*.exe) for running your application.
This is the best cross-platform installer creator i have found yet. You can get the java executable from here

How are Java applications deployed in the "real world"?

As a novice to the world of Java programming, this question has always boggled my mind. I first believed that all Java files were compacted into applets and then ran, but I soon realized that this isn't always the case. Could someone explain to me how we actually interweave our Java applications into a real product of everyday life?
TL;DR: How do we implement our code for practical usage?
It depends on the application. There are many options depending on how you want your users to use your app. Usually it's packaged as a jar or a specialized jar (war, ear).
In theory, you could zip the raw directory structure with your .class files in it and provide a shell script/instructions that run the java command for the user. I don't recommend this because it's kind of unprofessional and requires you to maintain a shell script for each OS you want to be able to run the program on.
Jar files are used to package libraries but you can also have a manifest file in it that says, "When someone double clicks/executes this, run this class". That class can start up a GUI or be a headless task that responds to the parameters, etc.
You can have applets, like you said. These programs are run in the user's browser.
You can have a war file, which is a way to package a web application. You give this to a web server and it knows how to deploy it so that you can visit the web pages. An example web server/container is tomcat or jetty.
You can have an ear file which can contain other war files inside it. This is used for applications that need other parts of the javaee functionality (ejbs, jms queues, etc.). An example of an application server is jboss or glassfish.
There's also java web start apps. These are apps you can run by visiting a webpage, but they get downloaded to your computer and run on the user's computer (instead of on the server's backend, like in a war/ear).
There's also javafx. I don't know anything about that though. By skimming the FAQ, it appears to be Java's answer to Adobe's Flex. You configure UI components with an xml configuration. I'm not sure what format JavaFX apps use, but it does say, "Deploy on the desktop or in the browser".
As Sotirios Delimanolis mentioned in a comment below, you can build these files with build systems like Ant or Maven. You can also build them "by hand" with the tools that come with the java/javaee sdk. For example, you should have a jar command in your path if you installed the sdk. Here are some details of these build systems:
Maven
High level (you tell it what to build, not how to build it)
Much more than just a build system. It also has dependency management, etc.
Opinionated (it uses convention over configuration, each config file generates 1 artifact, etc.)
Ant
Low level (you tell it how to build things)
Flexible
Config files can do whatever you want, build as many artifacts as you want
Easy to learn
SDK tools
Always up to date. EG: Very rarely, maven/ant may not be able to set a configuration option
Difficult to remember commands
Very low level
By itself, not repeatable (EG: unless you build a script, you will have to type the jar command yourself each time)
Applets never really caught on and are very rarely used nowadays.
Simple applications can be deployed as "executable" JAR files , which are basically ZIP archives with additional metadata that tells the JVM which class contains the main method to run. They can be run on the command line using the -jar option, or in most desktop environments by double-clicking (this requires a JVM to be installed as well).
Desktop applications can be deployed via Java Web Start or installers like IzPack or Install4J, but Java desktop applications are not very common either.
Most Java software nowadays runs only on servers (web servers or app servers). They are typically deployed as WAR or EAR files, which are also ZIP archives containing classes and other resources. These applications then run inside a server component following the Servlet or EJB standards.
If the application is mean to run on a client, it is packaged as an executable JAR, then further packaged as an Application Bundle (Mac), maybe wrapped in an exe (Windows), or paired with an executable script that will launch the JAR and set any required VM arguments.
If it is part of a web application, then it will be packaged as a WAR or EAR and placed into the appropriate location on the web server.
If it is simply a library, then it is usually packaged as a JAR (non-executable) and distributed as such for integration into larger projects.
applets and then ran, but I soon realized that this isn't always the case
Actually, applets are rare nowadays and their use is discouraged.
Create an executable jar, a war which is dropped into a web server or a library that is used by another project that is one of the previous two.

JNLP: How to specifying installation directory and data to download?

I wonder if one can let the user specify an installation directory for an application served by a JNLP file? For example:
INSTALLDIR: C:\Program Files\MyCompany\My Program\
Is that also possible to mention a data folder to be downloaded with the jnlp application jars in INSTALLDIR/data?
I wonder if one can let the user specify an installation directory for an application served by a JNLP file?
The user or their system administrator can configure the location of the cache using the Java Control Panel.
Is that also possible to mention a data folder to be downloaded with the jnlp application jars in INSTALLDIR/data?
There is no existing functionality, but if you can write Java code to achieve that, add it to a JNLP installer extension and that code will be called when the app. is first run. Here is a demo. of using the extension installer service.
Concerning installation directory, I fear that changing the cache path will change it for all other JNLP applications, isn't it?
Your fears are well founded, but there is a subtle implication you seem to have missed. Not only that, but even if it were possbile to find that directory in your app. (it is not possible for an applet or JWS app. to discover that information), it might be changed at any moment by the user (or their system administrator).
What I've been hoping you would infer from my messages so far is this. If your app. relies on knowing the installation directory, it is seriously broken. Fix that first.

CLASSPATH, Java Buld Path (eclipse), and WEB-INF\LIB : what to use, when, and why?

I recently switched to J2EE from .NET, and am confused about where to put JAR files. I know that the CLASSPATH, WEB-INF, and Eclipse's Java Web Path are all places where JARs can be stored, but I'm confused about which folder to use, when, and why.
First off, we have the CLASSPATH. I usually set this by going into "Environment Variables" inside "My Computer." I know that this is the default place where the Java compiler looks for JAR files. When I add a folder or a JAR to my CLASSPATH environment variable, why is it ignored by Eclipse, the Java compiler, and the web server?
Also, I know that WEB-INF\LIB is a place where you can put JAR files that your web app is going to use. However, I've put JARs in WEB-INF\LIB only to have them be ignored. In what situations should I put JARs into WEB-INF\LIB folder? How do I get Eclipse or the web server to notice them?
So far, the only thing that works for me is to actually change the Java Build Path for an Eclipse project. I'll select the JARs I need and hit "Add External JARs." Most of the time when I do this, Eclipse will recognize my JARs and read the classes therein. However, I've run into a bunch of weird random errors while doing this (mostly having to do with dependencies, I think). For some reason, I just get the feeling that this isn't the right way to do things, and that I'm missing some vital piece of information. When should I be manually Adding External JARs inside Eclipse, and when should I be doing things differently? How come Eclipse's Java Build Path doesn't seem to know about the folders in my CLASSPATH environment variable?
Really, I would just like to gain a better understanding of the CLASSPATH, Eclipse's Java Build Path, and the WEB-INF/LIB folder -- the purposes they serve, the relationships between them, and where I should be putting my JARs in various situations. I would appreciate any advice you could give me, or any articles that you could recommend.
Thank you.
The CLASSPATH you set in your environment affects only standalone Java applications, i.e. ones you run from a command prompt or an icon. As you've noticed, Eclipse ignores this. It sets up its own per-project classpaths.
javac and java, if called from the command prompt, should/may honor this path, but it's no longer considered great practice to do this. It's turned out that every app needs its own set of stuff, so a global CLASSPATH isn't really doing any of them any good. Modern practice is to simply specify the classpath with the -cp option on the command line for javac or java.
A standalone Web Application server will also set up its own classpath. From the command line or GUI, WebAppServers are usually started by a script (.BAT or .sh) that sets up a classpath using -cp. Tomcat has a directory called common or common/lib where it expects to see libraries that should be available the the server and all programs running under it. But you will generally not need/want to mess with this, as it's customaries for applications to provide their own library collectons in WEB-INF/lib.
So for a Web app, you'd put your varous jars into the lib directory, under WEB-INF, assuming Eclipse pre-builds such a directory structure for you.
All the libs you need also need to be made known to Eclipse. In the Project Explorer, I select the whole slew of them at once, right-click and select Build Path | add to build path. That's easier than messing with Eclipse's project build path manually.
Java has a long history and experience has shown that some ideas were good and some were bad.
The CLASSPATH environment variable was the initial way to tell the Java machine where to locate classes from your program, and works reasonably well for command line programs. It was rapidly found that this should not be a global thing (as that tend to mess things up in the long run) but a per-program thing. This could be done by creating a wrapper script/BAT-file which sets the variable and runs the Java machine.
All was well, then people wanted to write web server stuff in Java. The Servlet API was created where a web application is a stand-alone unit - this resulted in that the CLASSPATH for each web application is the unpacked files under WEB-INF/classes plus the jar-files under WEB-INF/lib. And only that. This means the global CLASSPATH variable is ignored. This has been found to be a VERY good thing, so the concept has migrated elsewhere.
For instance a "executable jar" (which Eclipse calls a "runnable jar") which is invoked with "java -jar foobar.jar" contains the complete classpath INSIDE the Jar in a special manifest file. Java Web Start which is used to start java programs from a web server explicily lists the full classpath in the configuration file on the server.
But, to get you started. If you want to write a Java web application:
Get the Eclipse Java EE version.
Create a new Dynamic Web Project e.g. named foobar.
Drag and drop (or copy/paste) the jar files you need in foobar/WebContent/WEB-INF/lib
Create a new file named foobar/WebContent/index.jsp. In the blank file type <h1>Hello World <%= new java.util.Date() %></h1>
Right click in editor for index.jsp, choose Run -> Run on Server, and choose the Basic -> J2EE preview at localhost server, and Finish.
A browser window will now open, either in a browser or inside Eclipse which will render your JSP-page. You can change the JSP-page, save it with Ctrl-S and reload the browser window to see the changes.
Also, I know that WEB-INF\LIB is a place where you can put JAR files that your web app is going to use. However, I've put JARs in WEB-INF\LIB only to have them be ignored. In what situations should I put JARs into WEB-INF\LIB folder? How do I get Eclipse or the web server to notice them?
The real problem you have here is likely that you didn't got Eclipse for Java EE developers and/or that you just created a generic Java Project instead of a Dynamic Web Project and built up the necessary folder structure yourself.
If you create a Dynamic Web Project in Eclipse for Java EE developers, then Eclipse will automagically add any libraries in WEB-INF/lib to the build path. The build path is roughly said just the classpath which is been used in both compiletime and runtime. With other words: just drop the 3rd party JAR's in there, really nothing more needs to be done.
Note that Java is case sensitive, thus it should be really called WEB-INF/lib, not WEB-INF/LIB. But anyway, if you create a Dynamic Web Project, then Eclipse will just automagically generate the correct folder/file structure for you.
As said by others, ignore the %CLASSPATH% environment variable. It is only used by javac.exe/java.exe and even then only when you do not specify any of the -cp, -classpath or -jar arguments. In real world this environment variable is seldom used, it is just some convenience for starters (and unfortunately also the most confusing one, they should never have invented it).
If you're dealing with web applications, /WEB-INF/lib is the portable place to put JARs. This is where web servers servlet containers expect to find an application's jar files.
Eclipse requires you to specify the path to your libraries, jar files (on Properties -> Java Build Path -> Libraries tab). This can be found on the .classpath project file.
Usually you have the JRE libs on its path (which would be on your classpath too), so adding the libs to the classpath and updating eclipse build path would work.
The WEB-INF directory should be the place that contains necessary information for your web application.
I'm not an Eclipse expert, but I think that your problem can be answered like this:
1) CLASSPATH is an environment variable that is read in when you launch java programs and is used by classloader to figure out where the classes are placed.
I would modify the CLASSPATH variable only in the case when you are launching an java program from a script, as this allows you to conveniently launch a program and make sure that the classes are found. This would not be the case for you, as you are developing the web application.
2) WEB-INF/lib is the directory under which the web application container's classloader (like tomcat or glassfish) looks into if your web application needs to resolve a class. So you put there the classes that are used in your web application.
Some IDE's do include the libraries/.jar files that you are using in a project automatically to the package.
3) Eclipse library/classpath resolving during the development time. I would assume, but apologies for assuming, as one really shouldn't do this ;), that you can define a library (add external .jar files to projects) and autocomplete/all the other interesting features should start working with this, as you basically make those classes visible for the IDE with that activity. I also would assume that you can then mark those libraries to be automatically added to the web projects etc., by the IDE.
In general a good reading about how classes are found during execution is here (it's a sun's official documentation). Also a good place to read about this is the ClassLoader class documentation.
Taken together the comments helped me as well. I had added all the jena .jars to the build path from eclipse but that wasn't sufficient. Following suggestion to "add to WEB-INF/lib" it seemed intuitive to drag from libraries folder to WEB-INF (from within eclipse), but that didn't work. Nor did copying the .jars to WEB-INF. I eventually drag-and-dropped from the windows desktop to the WEB-INF lib folder in Eclipse, and that fixed the problem. It would be nice if any .jars added to the build path were automatically copied to WEB-INF lib by Eclipse. In case it matters, this was eclipse EE IDE, Indigo release, on windows 7.

Deploy java (command line) app using Netbeans / ant

I've finally managed to create a Netbeans project out of an old standalone (not Web-) Java application which consisted only out of single .java sources. Now I have basically two questions regarding Netbeans Subversion interaction and application deployment:
Do you check in all the Netbeans project files into the repository, normally?
If I build the project using Netbeans (or ant) I get a .jar file and some additional jar libraries. In order for the app to run properly on the server, some additional config files and directories (log/ for example) are needed. The application itself is a J2SE application (no frameworks) which runs from the command line on a Linux platform. How would you deploy and install such an application? It would also be nice if I could see what version of app is currently installed (maybe by appending the version number to the installed app path).
Thanks for any tips.
No, not usually. Anything specific to NetBeans (or Eclipse, IntteliJ, etc), I don't check in; try to make it build from the command line with your ant script and produce exactly what you want. The build.xml is something that can be used for other IDEs, or in use with Anthill or CruiseControl for automated builds/continuous integration, so that should be checked in. Check in what is needed to produce/create your artifacts.
You don't specify what type of server, or what exact type of application. Some apps are deployed via JNLP/WebStart to be downloaded by multiple users, and have different rules than something deployed standalone for one user on a server to run with no GUI as a monitoring application. I cannot help you more with that unless you can give some more details about your application, the server environment, etc.
Regarding the config files, how do you access those? Are they static and never going to change (something you can load using a ResourceBundle)? ? You can add them to the jar file to look them up in the ResourceBundle, but it all depends on what you are doing there. If they have to be outside the jar file for modification without recompiling, have them copied with an installer script.
As for directories, must they already exist? Or does the application check for their existence, and create them if necessary? If the app can create them if absent, you have no need to create them. If they need to be there, you could make it part of the install script to create those folders before the jar files are installed.
Version number could be as simple as adding an about box somewhere in the app, and looking up the version string in a config/properties file. It has to be maintained, but at least you would be able to access something that would let you know you have deployed build 9876.5.4.321 (or whatever version numbering scheme you use).
Ideally, you should not tie down your application sources and config to a particular IDE.
Questionwise,
I suggest you do not. Keep you repository structure independent of the IDE
You might have to change your application so that it's structure is very generic and can be edited in any IDE.
Is this a web app? A standalone Java app? If you clarify these, it would be easier to answer your query.
We don't check in the /build or the /dist directories.
We tend to use this structure for our Netbeans projects in SVN:
/project1/
/trunk
/tags/
/1.0
/1.1
/binaries/
/1.0
/1.1
When a change is need we check out the netbeans project from trunk/ and make changes to it and check it back in. Once a release of the project is needed we do an SVN copy of the netbeans project files to the next tag version. We also take a copy of the deployable (JAR or WAR) and place it in the version directory under binaries along with any dependencies and config files.
By doing this we have a clean, versioned deployable that is separate from the source. Are deployables are version in the name - project1-1.0.jar, project1-1.1jar and so on.
I disagree with talonx about keeping your source non-IDE specific - by not storing IDE files in SVN along with you source you are adding extra complication to the checkout, change, checkin, deploy cycle. If you store the IDE project files in SVN you can simply check out the project, fire up the IDE and hit build. You don't have to go through the steps of setting up a new project in the IDE, including the files you SVNed, setting up dependencies etc. It saves time and means all developers are working with the same setup, which reduces errors and discrepancies. The last thing you want is for a developer to check out a project to make a small bug fix and have to spend time having to find dependencies and set stuff up.
To answer question #2 -- who's your consumer for this app?
If it's an internal app and only you (or other developers) are going to be deploying it, then what you have is perfectly all right. Throw in a README file explaining the required directories.
If you're sending it out to a client to install, that's a different question, and you should use an installer. There are a few installers out there that wrap an ant script and your resources, which is a nice approach particularly if you don't need the GUI... just write a simple ant script to put everything in the right place.
Version number is up to you -- naming the JARs isn't a bad idea. I also have a habit of printing out the version number on startup, which can come in handy.

Categories