Webstart, jar and resources

My game is running fine but it is all in one big jar (beside libs).

May be, should i split the jar (1 for the code, 1 for sprites, 1 by music) ?
For music, should i put the MP3 inside a jar (then use …getResource(“audio/music.mp3”)…) or should i use directly the files ( File("./audio/music.mp3"), i’m not sure if webstart allow to use something else than jar ) ?

You’re right, you put it inside the jar and do getResource. WebStart won’t let you write things to the disk unless you use the jnlp.jar sand-boxed functions. (java.util.Preferences methods still work though, thank goodness!).

The advantage of splitting it up are faster download of updates. Eg if the code is 100kb, textures are 1mb, and sound are 2mb, then clients would only have to download 100kb (instead of 3.1mb) if they want to play it again and you fixed one small bug in the meantime.

File does not work with webstart (if you want to load something from jars in general). Use URLs (getResource) and streams (getResourceAsStream).

How do you deal with several jars ?
For now, i have made a project by jar (i’m using Netbean). May be there is a way to make several jars in one project ?

One way is to make it into two separate projects, then compile and build (jar) one, then go to the other project and import the jar from the first project and then build the other project. Then you’ve got two separate jars. There’s probably a better way to do it, but I don’t know. Maybe you could ask on the www.netbeans.org forums

Go to the “Files” tab and navigate to your projects “src” folder. Move the directories for your resource out of the src folder to exclude them from the main jar, so you have for example the following folder structure:


+ <YourProject>
   + audio
   + nbproject
   + sprites
   + src
   (...)

Then open your build.xml file and add the following target:


    <target name="-post-jar">
        <mkdir dir="${dist.dir}/lib"/>
        <jar destfile="${dist.dir}/lib/${ant.project.name}-audio.jar" basedir="audio"/>
        <jar destfile="${dist.dir}/lib/${ant.project.name}-sprites.jar" basedir="sprites"/>
    </target>

This will create two additional jars under dist ("-audio.jar" and “-sprites.jar”) with the contents of your audio and sprites folder.

After that switch back to the “Projects” tab and open your projects properties. Add the “audio” and “sprites” folder to the run-time libraries under the “Run” tab in the “Libraries” category. This last step is required to let your app load from your resource folders when starting from within the IDE.

Clean and build the project.

To let NetBeans correctly create a JNLP file for Web Start, open the project properties, Go to the “Application->Web Start” category and check the “Enable Web Start” box. Now open the “Libraries” category and switch to the “Run” tab again. For the JNLP-File to include your resource jars they have to be referenced as run-time libraries, so add “-audio.jar” and “-sprites.jar” to the list, too.

Ok thanks. It create the jars ;D.

(I should really learn more about ant). How to i had those jar to the manifest ? (Class-Path: …)

Just add the jar locations comma separated relative to your executable jar:


Class-Path: lib/<YourProject>-audio.jar lib/<YourProject>-sprites.jar

Well, by modifying the manifest.mf in the project folder, i can launch the jar in command line. But when i launch in the IDE, it doesn’t find the audio/texture… it is base on a ant script and not on the manifest…
Well it is getting far too complicated to only create 2 jar files.

Did you include the “audio” and “sprites” folders to the runtime-libraries?

Another option would be just to leave the “audio” and “sprites” folder under “src” and exclude them from the main-jar by adding “, audio, sprites” to the “Exclude From Jar File” option under the “Build->Packaging” category of your project’s properties.

To generate the two additional jars again, the “-post-jar” target has to look like this:


    <target name="-post-jar">
        <mkdir dir="${dist.dir}/lib"/>
        <jar destfile="${dist.dir}/lib/${ant.project.name}-audio.jar" basedir="${src.dir}/audio"/>
        <jar destfile="${dist.dir}/lib/${ant.project.name}-sprites.jar" basedir="${src.dir}/sprites"/>
    </target>

despite using netbeans or another java IDE, the build.xml file can be replaced by a easier one, e.g. that one from the Apple XCode IDE for Java Ant. It’s shorter and easily configurable by hand-self.
here’s a sample of the build-jar target you can find at the CVS repository for my project :

<target name="build-jar" depends="compile" description="Build jar">
  101         <mkdir dir="${dist}"/>
  102         <mkdir dir="${resources.all.dir}"/>
  103         <mkdir dir="${resources.os.all.dir}"/>
  104         <mkdir dir="${resources.os.arch.dir}"/>
  105         <!-- First, copy the HTML into the ${dist} directory. -->
  106         <copy todir="${dist}" file="${html.file}"/>
  107         <!-- ******* resources files to ${dist} directory *****
  108 		<copy todir="${dist}/Images">
  109 			<fileset dir="${resources.dir}/Images">
  110 				<include name="**/*.*"/>
  111 			</fileset>
  112 		</copy>
  113 		<copy todir="${dist}/data">
  114 			<fileset refid="data.files"/>
  115 		</copy> disable -->
  116         <!-- policy file AppletViewer or java use it -->
  117         <copy file="${policy.file}" todir="${dist}"/>
  118         <!-- run file //-->
  119         <copy file="${run-osx.file}" todir="${dist}"/>
  120         <copy file="${run-win32.file}" todir="${dist}"/>
  121         <jar jarfile="${jarfile}"
  122              basedir="${bin}"
  123              manifest="${Manifest.file}"
  124              update="true"
  125              compress="true">
  126             <!-- Merge library jars into final jar file -->
  127             <zipgroupfileset refid="lib.all.jars"/>
  128             <zipgroupfileset refid="lib.os.all.jars"/>
  129             <zipgroupfileset refid="lib.os.arch.jars"/>
  130             <!-- ****** zip resources ******  -->
  131             <fileset refid="resources.all.files"/>
  132             <fileset refid="resources.os.all.files"/>
  133             <fileset refid="resources.os.arch.files"/>
  134             <!--disable for quicker build -->
  135         </jar>
  136     </target>

see lines 131-133 are the resources to add directly compressed to the .jar archive. it can be fit to your settings. http://sf3jswing.cvs.sourceforge.net/sf3jswing/AnimationDemo3/build.xml?view=markup is the source file. 8)
IMPORTANT NOTICE for the “newless clubies” : resources for inner-.jar usage MUST BE package ORDERED to the CLASSLOADER THAT CALLS FOR THE RESOURCE FILE, e.g. java.lang.Math.class.getResource(file) means that the file is located in the resources directory named /java/lang/ .

Don’t replace ant-files of a netbeans generated java project. This would break most of the project properties functionality as well as the library management. Only use custom ant files with freeform projects, but be aware that you will loose some IDE comfort when doing this.

Also I see no real benefits by avoiding the netbeans generated build files, since they are used transparent through the main build.xml which you can customize…

alright, but there are plenty of advantages to be able to customize your build ant file. By the way netbeans build.xml properties are not so useful as they can be talked so, above all the library path is always accessible in the project properties which will not affect the build.xml file. Moreover the classpath is changed when the app is run, whereas merging all libraries in the .jar archive is the proper way for minimizing compatibility defection issue.
Well if any of you can build a complete .exe or .app file with netbeans, let us know… but that’s not the topic.
;D

Actually there is no problem to customize a netbeans build.xml to do anything you want at any build process stage. See the comments in the standard netbeans project’s build.xml:


    There exist several targets which are by default empty and which can be 
    used for execution of your tasks. These targets are usually executed 
    before and after some main targets. They are: 

      -pre-init:                 called before initialization of project properties
      -post-init:                called after initialization of project properties
      -pre-compile:              called before javac compilation
      -post-compile:             called after javac compilation
      -pre-compile-single:       called before javac compilation of single file
      -post-compile-single:      called after javac compilation of single file
      -pre-compile-test:         called before javac compilation of JUnit tests
      -post-compile-test:        called after javac compilation of JUnit tests
      -pre-compile-test-single:  called before javac compilation of single JUnit test
      -post-compile-test-single: called after javac compilation of single JUunit test
      -pre-jar:                  called before JAR building
      -post-jar:                 called after JAR building
      -post-clean:               called after cleaning build products

    (Targets beginning with '-' are not intended to be called on their own.)

    Example of inserting an obfuscator after compilation could look like this:

        <target name="-post-compile">
            <obfuscate>
                <fileset dir="${build.classes.dir}"/>
            </obfuscate>
        </target>

    For list of available properties check the imported 
    nbproject/build-impl.xml file. 


It’s more like implementing abstract methods (with code completion) than writing scripts, but you can do everything you could do in a stand alone ant script. I too have some stand alone ant projects - nothings wrong with that - but there is also nothing wrong with utilizing an existing build template…

So, i put :

<target name="-pre-jar">
        <jar destfile="Music1.jar" basedir="audio"/>
        <jar destfile="Sprites.jar" basedir="sprites"/>
    </target>

in the build.xml

And i have added the 2 jars in the “Libraries”, it work fine (even if there is twince the jar file, but it is not a big problem). I have try to put the jar directly in the lib folder but it didn’t seem to work (error that it can’t delete the “dist” directory)