JMCS (Java Mariotti Common Software) is a collection of APIs and JAR files shared by all JMMC Java-based GUI applications (SearchCal, ModelFitting, ...).

Its primary goal is to centralize all shared functionalities (e.g menubar handling, about box window, ...) in order to provide our end users with a more consistent, feature-reach, desktop-class application family, as integrated as possible across each of the 3 main execution platforms of today, that are Linux, Mac OS X and Windows.

The ultimate goal is to leverage our end user knowledge of their favorite platform, to let them fill right at home while using our applications, thus improving the perceived quality of our products while factorizing and sharing our development efforts.

This page describes each JMCS main functionalities :

App Class : the main class from which JMCS-based applications shall derive

This class aim is to handle applications life cycle, divided in 3 sequential steps : intialization, execution and quitting.

For your application to benefit from JMCS, your main class shall derive from our App class, thus implementing each of its abstract methods : init() and execute() :

  • Your init() method shall contain all your application initialization code, like specific command-line option parsing, MVC objects allocation and initialization, GUI setup, ...
  • Your exec() method shall in fact contain no code at all, as long as your application GUI fully implement the reflex approach (e.g Observer/Observable and MVC patterns, ...) and has already been initialized in init(), but is provided to handle specific action once application initialization is done (e.g network connection setup, automatic query launch, ...).
  • Furthermore, you can also implement your own finish() method to manage your application life cycle end if needed (e.g unsaved modification handling, network connection abort, ...).

Once instantiated at runtime in your main() method, your App-derived class will automatically bring your application to life by :

  1. Initializing App internal mecanisms (ApplicationData.xml file parsing, shared logger setup, command line option parsing, shared functionalities setup) when calling super(...).
  2. Displaying a Splash screen (for at least 2 seconds), in order to let the end user know which application is about to start.
  3. Calling your init() method to fully setup your application GUI while the splash screen is shown.
  4. Discarding the Splash screen, in order to set your GUI as the frontmost window and let the end user freely use it.
  5. Calling your exec() method at last.

Here is a minimal JMCS-compliant application template :

import fr.jmmc.mcs.gui.*;
public class MyMainClass extends App {
    public MyMainClass(String[] args) {
        super(args); // App internal initialization
    }

    protected void init(String[] args) {
        // Add your application initialization code here...
    }

    protected void execute() {
        // Add your application execution code here...
    }

    public static void main(String[] args) {
        new MyMainClass(args);
    }
}

Application Data : how they are stored and used

All the data concerning your application shall be stored in an XML file (named ApplicationData.xml) in your application package, at the same level as your main class deriving from App. This file will be automatically loaded when your main class is instantiated. It contains information about :

Please note that if your package does not contain this file, a default minimalist one will be used instead to ensure degraded execution mode.

Here is a minimal ApplicationData.xml template :

<?xml version="1.0" encoding="UTF-8"?>
<ApplicationData link="http://www.jmmc.fr/myprogram"> <!-- URL to the application main webpage -->
    <program name="MyProgram" version="1.1.02"/>
    <compilation date="11/04/2008" compiler="g++-4.1"/>
    <text>This is a description of MyProgram to be shown in the About box.</text> <!-- can be empty -->
    <releasenotes>
        <release version="1.0">
            <prerelease version="1.0b1" tag="MPV1_0b1">
                <change>First release !</change>
            </prerelease>
        </release>
    </releasenotes>
</ApplicationData>

Application version

The application version is extracted from the ApplicationData.xml file. Your application gets some convenient methods to know the status of it:
  • YourApp.isAlphaVersion() ( e.g. : 1.0a2 )
  • YourApp.isBetaVersion() ( e.g. : 1.0b2 )
If both of them return false, your should run one production version.

Menu Bar : provided menu items and how to add application specific ones

An already populated menu bar is provided by default, with the following standard functionalities :
  • A File menu, with the mandatory Quit menu item that automatically queries your finish() method (if implemented) to ensure whether your application should exit or not.
  • An Edit menu, with fully functional Cut, Copy and Paste items, plus Preferences (disabled if none).
  • An Help menu, with:
    • A User Manual entry, if your application package contains the needed documentation format (automatically disabled otherwise).
    • A way for the end user to provide feedback to JMMC using a simple dedicated window.
    • A way for the end user to put your application acknowledgement notice in his clipboard for later pasting in his publication.
    • A way for the end user to get access to your application 'Hot News' RSS feed through his computer default Web browser.
    • A way for the end user to get access to your application release notes through his computer default Web browser.
    • A way for the end user to acces your application FAQ webpage through his computer default Web browser.
    • A way for the end user to view detailled information about your application using a simple dedicated window.

All those default menus can of course be extended with your own menus and menu items using :

  • ApplicationData.xml to describe your menus and menu items (standard, checkbox, sub-menu, separator, text description, linked Action).
  • RegisteredAction : your actions shall derive from this class in order to be semi-automatically linked to your menu items (using the same action class name and identifier as in ApplicationData.xml, thanks to ActionRegistrar - a singleton class dedicated to automatically keep track of all your application RegisteredAction).
One good practice is to declare classPath and action as public static final String members on your registeredActions.

Here is an example of how to add menu items insertion and creation in ApplicationData.xml :

<?xml version="1.0" encoding="UTF-8"?>
<ApplicationData link="http://www.myProgram.com/">
    ...
    <menubar>
        <menu label="File"> <!-- Extending the default File menu -->
            <menu label="Import" classpath="fr.jmmc.mcs.modjava.Actions" action="scaction1" icon="/fr/jmmc/test/import.png"/>
            <menu label="Export" classpath="fr.jmmc.mcs.modjava.Actions" action="scaction1"/>
        </menu>
        <menu label="Menu 1">
            <menu label="Item 1" classpath="fr.jmmc.mcs.modjava.Actions" action="mfaction1" accelerator="shift T" description="Raccourcis n-1 de Model fitting"/>
            <menu/> <!-- menu separator -->
            <menu label="Item 2" checkbox="true" classpath="fr.jmmc.mcs.modjava.Actions" action="mfaction5"/> <!-- checkbox item -->
        </menu>
        <menu label="Menu 2">
            <menu label="Item 1" classpath="fr.jmmc.mcs.modjava.Actions" action="scaction1"/> <!-- sub-menus -->
                <menu label="Item 1.1" classpath="fr.jmmc.mcs.modjava.Actions" action="scaction1"/>
                    <menu label="Item 1.1.1" classpath="fr.jmmc.mcs.modjava.Actions" action="scaction1"/>
                    <menu label="Item 1.1.2" classpath="fr.jmmc.mcs.modjava.Actions" action="scaction1" accelerator="I" checkbox="true"/> <!-- mixing styles -->
                </menu>
                <menu label="SearchCal 12" classpath="fr.jmmc.mcs.modjava.Actions" action="scaction1" accelerator="I"/>
            </menu>
        </menu>
    </menubar>
    ...
</ApplicationData>

Another benefit of using our menu bar infrastructure (apart from getting all the previously described functionalities for virtually 'free'), is to transparently handle different hosting platform specificities (e.g Mac OS X) in which standard menu bar hierarchy is different. This guarantees the best user experience for each platform user, so they don't have to re-learn application-vendor specific behaviour when they already know their default platform-specific application behaviour well.

File Choosers: how to restrict available file types based on file extensions

JMCS offers a shared FileFilterRepository class to achieve this. This singleton registers file extensions with their corresponding MIME types, so you can later retrieve them to pass the corresponding FileFilter instance to your JFileChooser. Here is the code you should add to use it:
...
    protected class OpenFileAction extends RegisteredAction
    {
        /** Class Path. This name is used to register to the ActionRegistrar */
        public final static String _classPath="fr.jmmc.package.OpenFileAction";
        /** Action name. This name is used to register to the ActionRegistrar */
        public final static String _actionName="openFile";


      /** Class logger */
      static java.util.logging.Logger _logger = java.util.logging.Logger.getLogger(classPath);

        FileFilterRepository _fileFilterRepository = FileFilterRepository.getInstance();
        String               _scvotMimeType        = "application/x-searchcal+votable+xml";

        public OpenFileAction()
        {
            super(_classPath,_actionName);
            ...

            _fileFilterRepository.put(_scvotMimeType, "scvot",
                "SearchCal VOTables (SCVOT)");
        }

        public void actionPerformed(java.awt.event.ActionEvent e)
        {
            // JFileChooser only allowing selection of '.scvot' files
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.setFileFilter(_fileFilterRepository.get(_scvotMimeType));
            ...
        }
    }
...

Loading Files on Startup : how to associate a file type that opens your application when double-clicked

You first have to tell 'Java Web Start' to generate a desktop application when user first start your software. You must also associate your application with the MIME type you want the OS to launch your app with. This is done by specifying any file extension and MIME type in the JNLP file, as shown hereafter:
<jnlp>
  ...
    <information>
        ...
        <shortcut>
            <desktop/>
        </shortcut>
        <association mime-type="application/x-searchcal+votable+xml" extensions="scvot">
            <icon href="FileIcon.png"/>
            <description>SearchCal reads and writes SCVOT files</description>
        </association>
        ...
    </information>
    ...
</jnlp>

Once the association is done on the OS level, you have to register one of your RegisteredAction instance as the default 'open' action in your application code. This enables your App instance to automatically run your dedicated open action if the OS passes any file reference during application startup time :

...
    protected class OpenFileAction extends RegisteredAction
    {
        public OpenFileAction(String classPath, String fieldName)
        {
            super(classPath, fieldName);

            flagAsOpenAction();
        }

        public void actionPerformed(java.awt.event.ActionEvent e)
        {
                // If the action was automatically triggered from App launch
                if (e.getSource() == ActionRegistrar.getInstance())
                {
                    // Add file opening code here
                }
                else // User clicked the menu item
                {
                    ...
                }
        }
    }
...

Release Notes : how they are automatically generated

Data from ApplicationData.xml is used to automatically generate release notes in HTML and RSS format when your application is deployed.

Please not that for URL attributes, every

&
character has to be replaced with
&amp;
, so you cannot simply copy and paste your URL in the file without a little reformatting beforehand.

Here is an example of how to add detailed release and change notes in ApplicationData.xml :

<?xml version="1.0" encoding="UTF-8"?>
<ApplicationData link="http://www.myProgram.com/">
    ...
    <releasenotes>
        <release version="1.1">
            <prerelease version="1.1b2" tag="MPV1_1b2">
                <change type="BUGFIX" id="applicationname/14" url="http://mariotti.fr/gnats?cmd=view%20audit-trail&amp;database=JMMC-SW&amp;pr=15">Fixed Bar algorithm bug</change>
                <change type="CHANGE">Moved Foo menu</change>
            </prerelease>
            <prerelease version="1.1b1" tag="MPV1_1b1">
                <change type="FEATURE">Added Foo menu</change>
                <change type="REQUEST">Speeded up Bar algorithm</change>
            </prerelease>
        </release>
        <release version="1.0">
            <prerelease version="1.0b1" tag="MPV1_0b1">
                <change>First release !!!</change>
            </prerelease>
        </release>
    </releasenotes>
    ...
</ApplicationData>

External Dependencies : how they are displayed in the About box

Data from ApplicationData.xml is used to automatically display dependencies (if any) in your application About box.

Here is an example of how to add detailed dependencies data in ApplicationData.xml :

<?xml version="1.0" encoding="UTF-8"?>
<ApplicationData link="http://www.myProgram.com/">
    ...
   <dependences>
        <package name="AppleJavaExtensions" description="toolkit to provide better user interface on Mac, provided by Apple, Inc." link="http://developer.apple.com/samplecode/AppleJavaExtensions/index.html"/>
        <package name="SAVOT" description="SearchCal uses source code created at the Centre de Donnees astronomiques de Strasbourg, France."/>
   </dependences>
    ...
</ApplicationData>

Acknowledgement Note : how to provide a specific one for your application

If no acknowledgement note is provided in ApplicationData.xml, a generic one will be synthesized instead.

Here is an example of how to add an acknowledgement note in ApplicationData.xml :

<?xml version="1.0" encoding="UTF-8"?>
<ApplicationData link="http://www.myProgram.com/">
    ...
    <acknowledgment>
        <![CDATA[@INPROCEEDINGS{2008SPIE.7013E..44T,
   author = {{Tallon-Bosc}, I. and {Tallon}, M. and {Thi{\'e}baut}, E. and 
   {B{\'e}chet}, C. and {Mella}, G. and {Lafrasse}, S. and {Chesneau}, O. and 
   {Domiciano de Souza}, A. and {Duvert}, G. and {Mourard}, D. and 
   {Petrov}, R. and {Vannier}, M.},
    title = "{LITpro: a model fitting software for optical interferometry}",
booktitle = {Society of Photo-Optical Instrumentation Engineers (SPIE) Conference Series},
     year = 2008,
   series = {Presented at the Society of Photo-Optical Instrumentation Engineers (SPIE) Conference},
   volume = 7013,
    month = jul,
      doi = {10.1117/12.788871},
   adsurl = {http://cdsads.u-strasbg.fr/abs/2008SPIE.7013E..44T},
  adsnote = {Provided by the SAO/NASA Astrophysics Data System}
}]]>
   </acknowledgment>
    ...
</ApplicationData>

Application Website : where are applications main webpage, release notes and FAQ

Each application in production shall be accessible on the JMMC website.

For example, for the ApplicationName application :

Here is a typical file tree of a deployed application :

/home/users/lafrasse/public_html/ApplicationName/
|-- ApplicationRelease.xml
|-- ApplicationName.jar
|-- ApplicationName.jnlp
|-- applicationReleaseToRss.xsl
|-- index.htm
|-- jar
|   |-- Jmcs.jar
|   `-- modapp.jar
|-- releasenotes.htm
|-- releasenotes.rss
`-- setDateOfReleases.xsl

Preferences : standardized preference file location and version handling

Your preference data handling class shall derive from our Preferences class. You will then get the following benefits:
  • Freely provided saveToFile() method, handling automatic serialization of your preferenced values.
  • Automatic preference file loading from end user expected (host operating system specific) default location, by just providing the preference filename through getPreferenceFilename() (shall be in the form of "fr.jmmc.YourApplicationName").
  • Automatic fallback to default values if no preference file already exists, by mandatory using setDefaultPreferences() to define each of your application default values and keys.
  • Automatic preference file versioning handling, by using getPreferencesVersionNumber() : each time you change your preference file structure (preference keys, value units, ...) you change the returned int and provide the corresponding conversion code in your updatePreferencesVersion() method to handle this automatically for the end user (so the user doesn't loose any prior settings while upgrading your application regularly).

The following data types can be used as values : String, Boolean, Int, Float and Color objects. Each values shall be identified using an unique string key, in the form of "abc.def.foo.bar". Values related to a same preference group (e.g "abc.def.foo.LOW", "abc.def.foo.MEDIUM", "abc.def.foo.HIGH") can be ordered through a specified integer index.

Logging Facilities : how you should handle execution traces in your application

Here is the code you should add to each of your classes, in order to use the mandatory standard java logging facilities.
import java.util.logging.*;
public class Complex {
    /** Logger */
    private static final Logger _logger = Logger.getLogger(Complex.class.getName());
    ...
}

JMCS-based applications are all able to define their logging verbosity using the -v command-line option immediately followed by the verbosity log level (from 0 to 5). You can also start the LOGGUI utility to dynamically manage logging while running an application using the -loggui command-line option. When launched using Java WebStart, you can also use this option by adding an to the <application-desc> element in the JNLP file, as shown hereafter:

<jnlp>
  ...
  <application-desc main-class="fr.jmmc.scalib.sclgui.SearchCalibrators">
    <argument>-loggui</argument>
  </application-desc>
</jnlp>

Splash Screen : the window automatically shown while your application launches

A splash screen window is automatically displayed during application initialization. It displays the JMMC logo, the application name and version number, and the copyright statement.

Please note that it can disabled in the App-derived class call to super(...) constructor.

About Box : the window giving application detailled information to end user

An about box window is already provided and linked to the appropriate menu item. It contains the JMMC logo, the application name and version number, plus a customizable description text, and a standard invite to use acknowledgement in end user publications, followed by a list of external dependencies (if provided in the ApplicationData.xml file).

Status Bar : a way to display ongoing process state to end user

You can use StatusBar to discreetly provide the end user with ongoing process status feedback, by simply adding an instance of this class (that extends JPanel) to your main window's bottom.

You can then set its message from anywhere in your application with StatusBar.show("Insert your message here..."); .

Search Field : a textfield dediicated to searching tasks

This widget (based on work from Elliott Hughes) can easily be used with an ActionListener to perform searches throughout your data or using webservices.

SearchField SHOULD ALWAYS be prefered to a standard one, as its shape is easily associated with searching capabilities by end users.

Star Resolver Widget : a SearchField getting star data from CDS Simbad for a given star name

This widget queries the CDS Simbad web service (using an internal thread) with a given star name using StarResolver, and store results in a Star instance.

For the time being, retrieved data are:

  • RA and DEC values in sexagesimal format;
  • RA and DEC values in degrees;
  • FLUX for V, I, J, H and K bands;
  • OTYPELIST;

StarResolver and StarResolverWidget each include a main() function demonstrating how to use them.

Window Centerer : a way to center windows on complex screen setup

You can use the WindowCenterer singleton to simply center a given Window on the main screen of an end user complex screen setup (e.g multiple monitor system).

Feedback Report : how bug and user remarks are routed back to the JMMC team

End user can easily give us feedback using our dedicated window available form the standard help menu. This facility collects, in addition to the user mail, feedback type and comment, the execution platform description, any exception stack traces, and logged traces if any (this is why it is important that you follow our logging conventions).

All those collected informations are then automatically sent to our web-based feedback system. Our PHP script then formats all the received data, and transmits it to our user support team for further examination. Please note that an automated "Thank you" mail (with a unique feedback ID for later tracking if needed) is also sent back to the contributing end user if he provided his mail address.

Help Window : how to harness the shared HTML-based help browser

  1. Add the HelpSet JAR file generation from a documentation module reference in the Makefile (man target) by invocking jmcsHTML2HelpSet JMMC-MAN-2600-0001 for example
  2. Check that this JAR is also installed by the Makefile
  3. Check that this JAR is also referenced in the JNLP (if any)

Please note that their was some known bug preventig the load of HelpSets embedded in JAR file launched from JNLP under JVM 1.5.0_16, that was worked around using a dedicated method found in HelpView.java

Shared Libraries : list of embedded usable third-party toolkits

You can find the list of included JAR files available for your application visiting the main jmcs doxygen page

TODO list

GuillaumeMella - 09 Sep 2011 - 10:48

declare the shared lib URL incluced in the jmcsDeployJnlp as external env var or whatever

GuillaumeMella - 15 May 2009 - 16:39

use jmcs ApplicationData.xml to follow developpements and use a default ApplicationData.xml file for the default init

GuillaumeMella - 15 Apr 2009 - 13:48

Add rss view on startup (with associated disabling preference). This feature could also be used to test network capability...related to proxy...

GuillaumeMella - 15 Apr 2009 - 13:39

Add one general JMCSFrame (that get one statusBar, one empty toolbar...) In fact this is now the case. You can get the frame associated to the App using App.getFrame().

GuillaumeMella - 18 Mar 2009 - 17:36

Add on dynamic widget for the status bar which display historic of previous messages

SylvainLafrasse - 18 Dec 2008 - 14:46

  • only deploy modified jar files to speed up jar signing and JNLP downloads

GuillaumeMella - 17 Dec 2008 - 15:34

  • add example to dispose GUI element into app.finish() when instantiated by another one (in this case, System.exit is not called )

GuillaumeMella - 17 Dec 2008 - 12:30

  • remove from ApplicationData.xml the version attribute element of program element and use first version attribute of release elements instead
Edit | Attach | Watch | Print version | History: r35 | r33 < r32 < r31 < r30 | Backlinks | Raw View | Raw edit | More topic actions...
Topic revision: r31 - 2011-09-09 - GuillaumeMella
 
  • Edit
  • Attach
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback