This page last changed on Jul 17, 2008 by jdeolive.

Overview

A new web administration tool based on the Apache Wicket framework.

Motivation
Proposal
Backwards Compatability
Feedback
Voting
Links

Proposed By

Justin Deoliveira

Assigned to Release

2.0

State

Accepted

Motivation

There has not much that has not been beaten to death about why we need a new user interface. But for those not familiar it boils down to the following problems with the current interface:

Hard to Maintain

While struts was the de-facto java web framework for quite some time it has issues. It is very configuration-centric and was developed before the ideology of "convention over configuration". What this means is that adding a (simple) new user interface component usually boils down to :

  • adding 1 jsp
  • adding 2 java classes (1 form, 1 action)
  • editing the sruts-config.xml file

Quite a bit of work when all you want to do is add a simple form.

Furthermore, the use of the "DTO" pattern also increases the number of classes that must be modified when making simple changes. For each object in the user interface tier (config) there is a mirror object in the data transfer (dto) tier. This essentially doubles the work of any change.

Apply/Save Cycle

Making use of a dto layer allows the user interface to "batch" up changes made by users and apply them all at once, as opposed to realizing changes whenever a form is submitted. While this has its benefits it is non-intuitive and users constantly forget to apply a change and are left wondering why something is not working.

Poor Terminology and Work Flow

Not much to say here, the current interface was developed by programmers for programmers. Much of the terminology used (DataStore, FeatureType, etc...) is foreign to the casual GIS user. The hierarchical nature of the user interface concepts also leads to a poor work flow.

Proposal

Apache Wicket is a powerful java web framework that enforces a true seperation between logic and presentation. The current stable version of Wicket is 1.3 and this proposal is written with 1.3 as the target.

Some familiarity with Wicket is required before reading this proposal. There are a number of great examples available.

Application Structure
Extensibility

Application Structure

Pay little attention to the mock ups for pages in this section. They are used to only provide context for the rest of the proposal. The actual layout and page will be designed by an actual web and interaction designer.

The following class diagram illustrates the major classes of the web application:

GeoServerApplication

In any Wicket application a subclass of org.apache.wicket.Application. It is the central class for the application. SpringWebApplication is a subclass of Application designed specifically for Spring applications. It provides access to the Spring ApplicationContext making it available for all the components in the web application.

class GeoServerApplication extends SpringWebApplication {

    /**
     * Returns the home page of the application.
     */
    public Class getHomePage() { 
        return GeoServerHomePage.class;
    }

    /**
     * Returns the spring application context.
     */
    public ApplicationContext getApplicationContext() {
        return internalGetApplicationContext();
    }
    
    /**
     * Returns the GeoServer configuration.
     */
    public GeoServer getGeoServer();
    
    /**
     * Returns the GeoServer catalog.
     */
    public Catalog getCatalog();
    
    /**
     * Returns the GeoServer resource loader.
     */
    public GeoServerResourceLoader getResourceLoader();
}

The class is quite basic. It provides the home page for the application, GeoServerHomePage, and a few of the major GeoServer components like the configuration, the catalog, and the resource loader.

GeoServerHomePage

The home page of the application which contains:

  • the GeoServer logo
  • a welcome paragraph
  • a login panel
  • links to the "main" pages of the application

Cannot resolve external resource into attachment.

class GeoServerHomePage extends WebPage {
  ...
}

Note that this page does not extend from GeoServerBasePage.

GeoServerBasePage

The parent of all pages other than the home page. This page defines all the components that are common to all pages such as navigation, login, bread crumb trail, etc... In Wicket this strategy is known as "markup inheritance" and is a common way to share look and feel among pages.

The following could be a potential layout:

Cannot resolve external resource into attachment.

DataPage

All data and resources are managed on this page. It provides links to operations such as:

  • adding/removing/editing namespaces / workspaces
  • adding/removing/editing data stores / coverage stores
  • adding/removing/editing feature types / coverages

An example:

Cannot resolve external resource into attachment.

ServicesPage

All W*S services are managed on this page. It provides a link to the configuration page of each service.

Cannot resolve external resource into attachment.

MapsPage

The notion of a map does not exist in the current GeoServer configuration or user interface.

All maps and layers are managed on this page. This page is all about "publishing" data and resources. Operations on this page include:

  • adding/removing/editing maps
  • adding/removing/editing layers and layer groupings to/from maps
  • previewing each layer in the map

Cannot resolve external resource into attachment.

AdminPage

All server administration options are managed on this page, like logging, proxy setup, etc..

Extensibility

One of the major requirements for the GeoServer webapp was extensibility: the ability for plugin writers to extend the user interface as well. One of the reasons Wicket won out was its flexibility in loading user interface components.

The pattern for building an extensible component is as follows. When a page or some other container is "building itself" it delegates out to the Spring context to load meta data about "child components" of which it is composed. This is best explained with an example.

Consider the home page of the application, GeoServerHomePage. This page provides a list of links to the main pages of the application. Producing a static list of these pages would look like the following:

//constructor
public GeoServerHomePage() {

   //add links
 add( new BookmarkablePageLink( "data", DataPage.class ) );
 add( new BookmarkablePageLink( "services", ServicesPage.class ) );
 add( new BookmarkablePageLink( "maps", MapsPage.class ) );
 add( new BookmarkablePageLink( "admin", AdminPage.class ) );
}

Now lets assume for the moment that instead of hard coding this list of links we want to instead make it extensible. To do this we first come up with an interface called MainPageInfo which will contain information or metadata about a main page in the application:

class MainPageInfo {

  String title;
  Class pageClass;

  /**
   * The title of the link.
   */
  String getTitle() {
     return title;
  }

  void setTitle( String title ) {
     this.title = title;
  }

  /**
   * The class of the page to link to.
   */
  Class getPageClass() {
     return pageClass;
  }

  void setPageClass( Class pageClass ) {
     this.pageClass = pageClass;
  }

}

Now instead of manually creating each link we delegate to the MapPageInfo extension point:

//constructor
public GeoServerHomePage() {

 //get application context
 GeoServerApplication app = (GeoServerApplication) getApplication();
 ApplicationContext ac = app.getApplicationContext();

 //look up extensions
 List<MainPageInfo> pages = ac.getBeansOfType( MainPageInfo.class );

 //add links
 for (MainPageInfo page : pages ) {
    add( new BookmarkablePageLink( page.getTitle(), page.getPageClass() ) );
 }

}

This code example is not 100% correct but gets the point across

Each extension must be registered in a spring context as follows:

<bean id="dataPageLink" class="org.geoserver.web.MainPageInfo">
  <property name="title" value="data"/>
  <property name="pageClass" value="org.geoserver.web.data.DataPage"/>
<bean>

This strategy extends to other components as well. Instead of plugging in pages, one may wish to plug in tabs to a tabbed panel. The same strategy above holds:

  • define a class which contains metadata about the extending component
  • register instances of the extending components metadata in a spring context
  • process the extension point while composing the extensible component

Consider the following class diagram:

To define a page extension point we create a subclass of WebPageInfo:

class MainPageInfo extends WebPageInfo<GeoServerBasePage> {

}

And loading extensions becomes:

GeoServerExtensions.extensions( MainPageInfo.class );

Feedback

Backwards Compatibility

The Wicket based interface will be entirely new code, leaving the current interface untouched. The only backwards compatibility issues will be with the script hacks people have come up with to apply changes to GeoServer programatically.

Voting

Andrea Aime: +1
Alessio Fabiani: +1
Justin Deoliveira: +1
[~jgarnett]: +1
[~sfarber]: +1
[~roba]: +1

Links

[JIRA Task|]
[Email Discussion|]
[Wiki Page|]


cd.png (image/png)
ext.png (image/png)
Document generated by Confluence on May 14, 2014 23:00