This project implements a desktop service which other client-side applications can connect with to interact with astrogrid. At present supports HTTP / XML-RPC / Java-RMI / Gui interfaces to astrogrid client-side components. Maybe add CORBA later.
The client runtime provides a single sign-on, single-configuration, and single cache for interactions with astrogrid servers - making implementation of client-side applications simpler.
The runtime provides client-side components for accessing the basic functionality of each of the astrogrid services - myspace, registry, jes, cea, community. It also provides GUI components - simple dialogues that can be reused by client applications to perform common tasks (myspace microbrowser, registry browser, etc). Finally, the runtime provides a series of simple GUI applications that act as reference implementations for GUIs for the core features of astrogrid - myspace browser, job controller, registry browser. Others to follow - workflow builder, query builder, cea invoker.
The interfaces to these components can be found in the ACR Interface project.
Advice and hints to simplify writing code in the Workbench.
Run maven eclipse to set up your classpath from the impl sub project. You need to also have the maven-base and aggregate projects checked out at the correct relative locations. Don't try and assemble the classpath by yourself - it's huge, and doing this most likely will lead to hidden mismatches between library versions.
The workbench is organized internally into modules - these contain components with related functionality. Each module is defined by an xml file - the module descriptor called, by convention module.xml. There's an (incomplete) DTD in the source tree for this format - a schema needs to be written, as some of the module.xml structure (embedded XHTML) can't be easily described in a DTD.
The module descriptor defines which components to instantiate, and provides human-readable information about the module and the components within it. This information is used to generate the workbench GUI interface, and also the HTML and XMLRPC interfaces to the components.
For each component in the module, it defines the component name, public interface class, implementation class, and then documents the methods available on each component.
In the module descriptor, it's possible to set 'property' keys - for a module, component, method, or parameter. This provided me with a quick-and-dirty way of adding arbitrary metadata to the descriptor while I was prototyping the system. However, property keys defeat the point of a strongly-typed schema - so later I plan to rework the schema so that the commonest property keys are translated to elements. However, for now be aware that there's some magic keys, concerned mostly with how things are presented in the GUI and XMLRPC interfaces -e.g. icons and titles to use, technique to use to present the results, etc.
It's possible to define 'conditional' components in the module descriptor - these only become available when a condition is true (e.g. certain classes are available). Extending on this, it's also possible to define a component that provides more than one implementation class - the correct implementation to use is selected via a condition. See the module descriptor for the system module for an example of this.
A component has two parts - a public interface (in the api project) and a private implementation class (in the impl project).
The public interface should just define the methods that clients are able to call. Because of the technology used (javaRMI, xmlrpc) there's limits on the types that can be used as return values and parameters - in particlar, things needs to be serializable, and available on the clients classpath. This means using java-standard class (e.g. java.net.URI) rather than our own classes (org.astrogrid.Ivorn - which is buggy anyhow). Furthermore, only exceptions that extend from org.astrogrid.acr.ACRException should be thrown - and certainly no runtime exceptions thrown.
Some components also provide hidden internal interfaces - these contain extra methods that are really handy to have, but which have parameter types that can't be passed over RMI, and so can't be part of the public interface. Internal interfaces have the same name as the corresponding public interface, suffixed with Internal. These interfaces are found in the same package as the implementation class. Try to minimize the use of internal interfaces where possible.
A component is described in a module descriptor, which specifies the class names of the public interface and implementation class to use. The implementation class is instantiated lazily by the workbench when that component is needed. Only a single instance of each component is produced.
An implementation will typically depend on other, lower level components - for example configuration, help system, and maybe some of the components in the astrogrid module such as Registry. An implementation can gain instances of the components it depends on by declaring the interfaces in it's constructor. This is the typical pattern:
public class MyComponent {
public MyComponent(Registry reg,Configuration conf,MySpaceInternal msi) {
this.reg = reg;
this.conf = conf;
this.msi = msi;
}
private final Registry reg;
private final Configuration conf;
private final MySpaceInternal msi;
// ...
}
The workbench container takes care of providing the required components when it instantiates the class. Note that this means all dependencies the class may need have to
be declared in the constructor - there's no way to get at more later. Public or Internal interface can be used as dependencies - other classes or interfaces won't work. Finally, it's not
possible to cast from an interface to the implementation class.
The public interfaces to components and the methods they provide are documented in the acr api javadoc.
Try to avoid using the astrogrid delegate classes - use the equivalent components of the ACR instead. They're better integrated into the system than the delegates. Any code using delegates is liable to be refactored.
However, there are some AG libs that are useful to have - e.g. the xml marshalling in workflow-objects, and some of the utilities in the common project. All these are already available on the classpath.
For new classes, follow the rule that components and supporting classes for a single module stay in a single package wherever possible. At the moment there's some workflow-editor classes in modules.system and modules.dialogs that need to be refactored into modules.ui. For very large modules, use sub-packages as needed.
The public interfaces to components shold be placed in the 'api' subproject - this forms the published interface to the ACR. Please don't add or change interfaces in the api subproject without consultation - as this interface needs to be stable and self-contained to be usable by external clients.
UI Components are just the same as other components of the workbench - they have a public interface, and need to be defined in a module descriptor.
Most of the UI component implementations extend the class org.astrogrid.desktop.modules.ui.UIComponent. This provides a standard frame with an indeterminate progress bar at the bottom, helper metods to show progress and dialogues, plus a worker class that can be extended to do background processing. See the implementation javadoc for more details.
As is typical in swing programming, any long running activity (e.g. calling any webservice) should be executed on a background thread so that the responsiveness of the UI is maintained. This is particularly important when there is more than one window displayed by the application.
When using dialogues, prefer the component version instead of instantiating and creating the dialogue widget yourself - this means that the same dialogue is cached and reused. Furthermore, the component version is synchronized, which ensures that two separate parts of the UI can't throw up a modal dialogue at the same time (as this can lead to lockups).
There's a bunch of icons in the package org.astrogrid.desktop.icons - mostly cribbed from eclipse (which is a great source of reusable icons). Please try to use icons consistently (e.g. reuse the same icon for save, etc), and if you need to add more icons to this package, take them from eclipse - so a consistent look and feel is maintained. The class org.astrogrid.desktop.icons.IconHelper makes it trivial to load an icon.
There's some unit tests for those classes that can be easily split out. Most non-ui things are exercised by the system tests.
At the moment there's system tests that exercise all the methods in the astrogrid and system modules. The methods require astrogrid services to connect to. I run them against the production environment (which is what the workbench is configured for by default). Provide a username and password in the astrogrid.properties file in the test source tree.
The system tests use org.astrogrid.desktop.framework.ACRTestSetup to create an in-processes Workbench (ACR). The classes of the public interface - Finder and ACR can then be used to retrive an instance of a component for testing.
None as yet. Need to spend time looking at Abbot, and integrate this with the system test framework.
To run a local instance of the workbench, run the class org.astrogrid.desktop.Main from within eclipse. When running locally, some features (e.g. JavaWebstart and JDIC integration) won't be available. However, the system should degrade gracefully and use fallbalks (although a few exceptions will be thrown in the logs). If you want to avoid the exceptions (and have the JDIC integration), here's a tip: