Geomajas Community Documentation

Geomajas user guide for developers

Geomajas Developers and Geosparc

v1.6.0


I. Introduction
1. Preface
1.1. About this document
1.2. About this project
1.3. License information
1.4. Author information
II. Getting started
2. Starting a new GWT based Geomajas project
2.1. Prerequisites / Command line
2.2. Eclipse
2.3. IntelliJ IDEA
2.4. NetBeans
III. Architecture
3. Architecture
3.1. Command
3.2. Pipelines
3.2.1. Pipeline architecture
3.2.2. Application in the back-end
3.3. Layer
3.4. Security
3.4.1. Security architecture
3.4.2. How is this applied ?
3.4.3. Server configuration
4. Project structure
4.1. Module Overview
IV. back-end
5. Plug-ins
6. Configuration
6.1. General principles
6.2. Back-end configuration
6.2.1. Security configuration
6.2.2. Transaction configuration
6.2.3. Raster layer configuration
6.2.4. Vector layer configuration
6.3. Client configuration
6.3.1. Map configuration
6.3.2. Client layer configuration
7. API
7.1. API annotation
7.2. Back-end API
7.3. Command and plug-in API
7.4. GWT face API
7.5. API compatibility and Geomajas versions
8. Commands
8.1. Provided commands
8.2. Writing your own commands
9. Layers
9.1. Writing your own layer
10. Security
10.1. Authentication versus authorization
10.2. What can be authorized
10.3. Springsecurity module configuration
10.4. Writing your own security service
V. GWT face
11. GWT face architecture
11.1. Client-server communication
11.2. The map's model
11.2.1. MapModel
11.2.2. MapView
11.2.3. Workflow
11.2.4. Selection of features
11.3. The spatial package
11.3.1. Geometry definitions
11.3.2. Editing geometries
11.3.3. Snapping
11.4. Graphics & rendering
11.4.1. GFX interfaces
11.4.2. Rendering manual
11.5. User interaction
11.5.1. Toolbar: ToolbarAction
11.5.2. Toolbar: ToolbarModalAction
11.5.3. LayerTree: LayerTreeAction
11.5.4. LayerTree: LayerTreeModalAction
11.5.5. Menu: MenuAction
11.5.6. Controllers on the map
11.6. Internationalization in Geomajas
11.7. Unit testing GWT widgets
12. GWT widgets
12.1. GraphicsWidget
12.2. MapWidget
12.3. OverviewMap
12.4. Toolbar
12.5. LayerTree
12.6. Legend
12.7. FeatureListGrid
12.8. FeatureAttributeWindow
12.9. ActivityMonitor
12.10. ScaleSelect
12.11. FeatureSearch
VI. dojo face
13. dojo Configuration
13.1. Using Google maps raster layer
14. dojo Widgets
15. dojo example application
15.1. Project layout
15.2. Maven dojo plug-in
VII. Appendices
A. Migrating between Geomajas versions
A.1. Migrating from Geomajas 1.5.4 to Geomajas 1.6.0
A.2. Migrating from Geomajas 1.5.3 to Geomajas 1.5.4
A.3. Migrating from Geomajas 1.5.2 to Geomajas 1.5.3
A.3.1. General API changes
A.3.2. Configuration changes
A.4. Migrating from Geomajas 1.5.1 to Geomajas 1.5.2
A.5. Migrating from Geomajas 1.5.0 to Geomajas 1.5.1
A.6. Migrating from Geomajas 1.4.x to 1.5.0

Copyright © 2009 Geosparc nv.

Licensed under the GNU Affero General Public License. You may obtain a copy of the License at http://www.gnu.org/licenses/

This program is distributed in the hope that it will be useful, but without any warranty ; without even the implied warranty of merchantability or fitness for a particular purpose . See the GNU Affero General Public License for more details.

The project also depends on various other open source projects which have their respective licenses.

From the Geomajas source (possibly specific module), the dependencies can be displayed using the "mvn dependency:tree" command.

For the dependencies of the Geomajas back-end, we only allow dependencies which are freely distributable for commercial puposes (this for example excludes GPL and AGPL licensed dependencies).

Geomajas uses the Apache Maven project management tool for its build and documentation process. Thanks to Maven , the easiest way to start using Geomajas is by creating a new project using the Maven archetype. This will create a simple working project that you can use as starting point.

As the simple project is created using the Maven archetype, you will need to install Maven on your system, which can be downloaded from http://maven.apache.org/. We recommend using the latest stable version (2.2.1 at the time of writing). Installing Maven is quite simple: just unzip the distribution file in the directory of your choice and make some environment changes so you can access the executable. More information for your specific OS can be found at the bottom of http://maven.apache.org/download.html.

When Maven is installed you can create a base project using the following command line:


You first have to select the archetype you want to build (geomajas-gwt-archetype). Then it will ask you the "groupId", "artifactId", version and base package. Once you confirmed the settings, the project will be created in a subdirectory with a name equalling the "artifactId" you choose.


From the project root, you can immediately compile, test (using jetty as servlet container), or run the application in development mode using the following commands.


The "jetty:run" variant will immediately start a jetty server and start the application. This way, you can test your application at full speed (as when deployed). The application can be accessed at http://localhost:8080/.

The "gwt:run" option allows you to start the application in GWT development mode. A console will appear which allows starting your application (from the browser). Amongst other things, this allows you to see the messages GWT generates and see the output of the "GWT.log" commands.

Geomajas is an application framework which allows building powerful GIS application. We will try to look at the architecture starting from a high level overview, drilling down to discover more details.

At the highest level, Geomajas makes a distinction between the back-end and faces.


The back-end is where you configure your maps, layers and attributes/features. It is always server side. The back-end has an API for interaction with the outside world and for extension using plug-ins. While one of the main purposes of the back-end is to provide bitmaps and vector graphics for the maps and provide data about features to be rendered and edited, it contains no display code.

The actual display and editing is done in the faces. The back-end is agnostic of web (or other) display frameworks. Faces are often split in two modules, a sever-side module (which directly talks to the back-end using java calls) and serializes data to the client, and a client-side module which only talks to the server side module. The communication between the two modules is private to the face. The face itself provides a additional client API. This will typically provide details about available widgets, parameters for these widgets and other possible interactions (like message queues or topics you can subscribe to).

The purpose of Geomajas is to provide rich editing of GIS data in the browser, but the faces also make other applications possible. You could unlock the maps which are configured in Geomajas using a face which makes data available as web services (this would result in a face with only a server-side module). You could also build a java swing application using the Geomajas back-end by writing a swing face. This would result in a thick client application (possibly accessible using Java Web Start).

Geomajas contains two faces out-of-the-box.

The a dojo face, which uses the dojo toolkit JavaScript widget library in the browser, is mainly provided for backward compatibility. Up until Geomajas 1.4 this was the only face which existed. It integrates well with dojo but has the disadvantage that you need to develop in both java (for the server side) and JavaScript (for the client side) and that debugging can be a challenge.

Since 1.5 we also provide a GWT face. This allows all development to be done in Java and GWT will handle conversion to Javascript for code which needs to run in the browser. Obviously this integrates best with GWT based applications, but it can be combined with other web frameworks as well.


The Geomajas back-end is itself built from several modules which are tied together using the Spring framework (http://springframework.org/). The Geomajas-api module is a set of interfaces which shields implementation details between the different modules. The base plumbing and some generic features are provided by the Geomajas-impl module.

There are four possible ways to extend the back-end.

  • command : commands are used as main interaction point between the face (client side) and the Geomajas back-end. The retrieval of maps and features, calculations, updates on the features and all all other functionalities which are available client-side are done using commands.

  • layer : this groups a set of access options for all details of the layers of a map. A layer can be either raster or vector based. A vector layer can be editable. The features describing the objects which are part of the vector layer are accessed through the "feature model" which converts generic feature objects into something Geomajas can use (this way, there is no need for the generic feature objects to implement a "feature" interface, allowing the use of pojos). A feature contains a geometry and can contain attributes, style and labels. Attributes can be complex, including one-to-many and many-to-one relations to other objects.

  • pipeline : all Geomajas back-end services which deal with layers are implemented using pipelines. A pipeline is a list of steps (actions) executed in order. Each pipeline can be overwritten for a layer, or you can change the default which is used when not overwritten for a layer.

    Configuring pipelines can be used to change the rendering method, add additional rendering steps (for example marking the editable area on a tile), to introduce caching,...

  • security : these modules contain the pluggable security features. You can configure the security services which are used to verify the validity of an authentication token and return the authorization objects based on it. These authorization objects can read the security policies from your (secure) policy store.


The interaction of the client faces with the Geomajas back-end is handled using commands.

  1. When a command needs to be invoked (probably as result of a user interaction), the client will build a CommandRequest object. This contains the name of the command to be used, the parameters for the command, and optionally the user authentication token and language of the user interface.

  2. This object is transferred to the face server. For web applications, this will typically be done using an AJAX request.

  3. The face server will use this CommandRequest to invoke the CommandDispatcher service, which can be obtained using the Spring context.

  4. The CommandDispatcher will start by invoking the SecurityManager to check whether the execution of the requested command is allowed. If it is allowed, the actual Command is obtained using the Spring context. The CommandResponse object is created and the command is executed.

  5. The Command will now do its job, writing the results in the CommandResponse object. When problems occur during execution of the command, it can either write this into the response object or throw an exception.

  6. When the command has executed, if it threw an exception, the dispatcher will add this in the response object. It will then convert any exceptions in the response object into some messages which may be sensible to the user (put the message in the correct language in the result object, assuring the "cause" chain is also included). Some extra information is also added in the response object (like command execution time).

  7. The CommandResponse is returned to the face server.

  8. The face server serializes the CommandResponse back to the face client.

When the command had something to do with rendering, then the response object is likely to contain a Tile.

All the layer access services provided by the Geomajas back-end are implemented by invoking a pipeline. Using PipelineService, blocks of functionality become reusable and highly configurable with limited coupling between the pipeline step s.

Some of the services which are implemented as PipelineService include

  • RasterLayerService: methods for accessing a raster layer, especially getting tiles for a raster layer.

  • VectorLayerService: methods for accessing a vector layer, for example for getting the features or obtaining vector tiles

Pipelines can nest. One of the steps in the default "vectorLayer.saveOrUpdate" pipeline will loop over all features to be updated and invoke the "vectorLayer.saveOrUpdateOne" pipeline for each.

Pipelines are server side only, client access is typically made available by invoking a command.

Pipelines are typically invoked for a specific layer. In that case, the default pipeline can be replaced by a layer specific pipeline. This way, layer specific configurations (like optimizations or specific rendering) can be applied. When a layer does not overwrite a pipeline, the default is used. Pipelines are always selected on pipeline name. You can create the layer specific pipeline by setting the layer id for which it applied. When several pipelines have the same steps, you can define the pipeline once, and refer to it later by using a pipeline delegate instead of a list of steps.

A pipeline consists of a number of steps. A pipeline is configured using a PipelineInfo object which details the pipeline id and steps. When a pipeline is started (using the PipelineService) it executes the pipeline steps until the pipeline is finished (a status which can be set by one of the steps), or until no more steps are available in the pipeline. Each step gets two parameters.

  • a context which contains a map of (typed) objects which can be used to pass data between the steps (including initial parameters for the pipeline).

  • the result object which can be filled or transformed during the pipeline's execution.

The data which is accessed using Geomajas can be security sensitive.

Geomajas is built to be entirely independent of the authentication mechanism and the way to store policies.

Based on the user who is logged into the system, the following restrictions can apply:

  • access rights to a command

  • access rights for a layer

  • a filter which needs to be applied for a layer

  • a region which limits the data which may be accessed for a layer

  • access rights on the features

  • access rights on the individual attributes of the features


To assure the authentication mechanism is pluggable, an authentication token is used. The authentication token is used to determine the security context . The security context contains the policies which apply and which can be queried.

A list of security services can be defined (using Spring bean security.SecurityInfo). This list can be overwritten in configuration. By default the list is empty, which prohibits all access to everyone. The back-end does however include a security service which can be used to allow all access to everyone.

The security service is responsible for converting the authentication token into a list of authorization objects . The security manager will loop all configured security services (using Spring bean security.SecurityInfo) to find all the authorization objects which apply for the token. By default the security manager will stop looping once one of the security services gave a result. You can change this behaviour to always combine the authorization objects from all security services.

Note

The system explicitly allows authentication tokens to be generated by different authentication servers. In that case for each authentication server, at least one security service should be configured in Geomajas. However, when using such a configuration, you have to verify that the authentication tokens which are generated by the different servers cannot be the same.

In many systems (including RBAC systems) an authorization object matches a roles for the authenticated user.

Note that, as the actual authentication mechanisms are handled by the security services, Geomajas does not know any passwords or credentials. Similarly the secure, tamper-proof storage of policies is not handled by Geomajas either.

Details about the current authentication token and access to the policies (using the authorization objects) is available using the SecurityContext. The security context is thread specific. When threads are reused between different users, the security context needs to be cleared at the end of a request (group). This is normally handled by the faces.

The following general authorization checks exist:

  • isToolAuthorized(String toolId): true when the tool can be used. The "toolId" matches the "id" parameter which is used in the configuration as specified using the ToolInfo class.

  • isCommandAuthorized(String commandName): true when the command is allowed to be called. The "commandName" parameter is the same as the command name which is passed to the CommandDispatcher service.

And for each layer:

  • isLayerVisible(String layerId): true when (part of) the layer is visible.

  • isLayerUpdateAuthorized(String layerId): true when (some of) the visible features may be editable.

  • isLayerCreateAuthorized(String layerId): true when there is an area in which features can be created.

  • isLayerDeleteAuthorized(String layerId): true when (some of) the visible features may be deleted.

  • getVisibleArea(String layerId): only the area inside the returned geometry is visible (uses layer coordinate space). All features which fall outside the layer's MaxExtent area are also considered not visible.

  • getUpdateAuthorizedArea(String layerId): only the area inside the returned geometry may contain updatable features (uses layer coordinate space). All features which fall outside the layer's MaxExtent area are also considered not updatable.

  • getCreateAuthorizedArea(String layerId): only the area inside the returned geometry can new features be created (uses layer coordinate space). All features which fall outside the layer's MaxExtent area are also considered not creatable.

  • getDeleteAuthorizedArea(String layerId): only the area inside the returned geometry may contain deletable features (uses layer coordinate space). All features which fall outside the layer's MaxExtent area are also considered not deletable.

  • getFeatureFilter(String layerId): get an additional filter which needs to be applied when querying the layer's features.

  • isFeatureVisible(String layerId, InternalFeature feature): check the visibility of a feature.

  • isFeatureUpdateAuthorized(String layerId, InternalFeature feature): check whether a feature is editable.

  • isFeatureUpdateAuthorized(String layerId, InternalFeature oldFeature, InternalFeature newFeature): check whether the update contained in the feature is allowed to be saved.

  • isFeatureCreateAuthorized(String layerId, InternalFeature feature): check whether a feature is allowed to be created.

  • isFeatureDeleteAuthorized(String layerId, InternalFeature feature): check whether deleting the specific feature is allowed.

  • isAttributeReadable(String layerId, InternalFeature feature, String attributeName): check the readability of an attribute. The result can be feature specific.

  • isAttributeWritable(String layerId, InternalFeature feature, String attributeName): check whether an attribute is editable. The result can be feature specific.

These authorizations are split in several groups. The security service is not required to provide an implementation of each authorization test (see API), the security context always ensures that all methods are available.

Checking authentication and fetching the authorization details can be time consuming (not to mention the hassle of logging in again). To solve this, the results of the security services can be cached. When a security service can authenticate a token, the reply can contain details about the allowed caching. Three parameters are allowed to be passed, the validUntil and invalidAfter timestamps and an extendValid duration.

The security manager first checks the cache to find (valid) authentication results. A cache entry is only valid until the "validUntil" timestamp. When an entry is valid, validUntil may be extended until "now" plus "extendValid" duration. However, "validUntil" is never extended past "invalidAfter". When no data can be found in the cache, the security services are queried.

Note

There may be multiple authentications stored for a authentication token. When one of them becomes invalid, they are all considered invalid.

Note

Entering credentials is never handled by Geomajas. When the authentication token cannot be verified, a security exception is thrown. It is up to the client application (the face probably) to assure that a new authentication token is created.

The authorization have two possible results. When reading or rendering, all unauthorized data should simply be filtered without warning or exception. When trying to invoke a command or to create, update or delete, any attempt which is not authorized should result in a security exception.

The security uses the approach that all access is forbidden unless is is allowed. Hence, you will always need to configure at least one security service to assure the system is usable.

The security is applied throughout Geomajas. A list of places (which is not necessarily complete) and some additional ideas for application follow.

Back-end services:

  • CommandDispatcher verifies the existence of a SecurityContext and creates one if needed.

  • CommandDispatcher verifies whether the command is allowed to be used.

VectorLayerService:

  • Check layer access.

  • Handle the "filter" for the layer (if any).

  • Filter on visible area as this can increase query speed.

  • Post-process features filtering unreadable attributes, set update flags, remove features which are not allowed.

Commands:

  • configuration.Get and configuration.GetMap: layers which are invisible should be removed, tools which are not authorized should be removed, "editable" and "deletable" statusses on layers, features, attributes need to be set.

  • configuration.UserMaximumExtent: max extent should only consider visible features.

  • feature.PersistTransaction: making changes to attributes which are not editable should cause a security exception.

  • feature.SearchByLocation: only return visible features and readable attributes.

  • feature.SearchFeature: only return visible features and readable attributes.

  • geometry.Get: only return the geometry for visible features.

  • geometry.MergePolygon: no security implications.

  • geometry.SplitPolygon: no security implications.

  • render.GetRasterTiles: should only return data for visible layers, ideally post-processing the image to ensure only visible area is included (making the rest transparent).

  • render.GetVectorTile: should only return data for visible layers, only display visible features, only return visible features, only render visible features. When attributes need to be included, only readable attributes should be included and the "editable" flag needs to be set.

Rendering:

  • The individual rendering steps (especially the layer/feature model) can use the SecurityContext to filter the data they produce.

  • Images can have areas masked which are not allowed to be seen.

  • The rendering pipeline can include steps which check the security. This can make life easier on the layer model which are not guaranteed (or forced) to handle all security aspects. These are active by default but can be removed for speed (when you are sure this is double work).

Cache:

  • The caching needs to consider the access rights when storing and retrieving data.

Face:

  • The face is responsible for assuring a authentication token is included in all access to the back-end.

  • The "get configuration" commands filter the data to assure invisible layer and attributes and tools which are not allowed are not displayed. No action needed.

  • Specific tests on editability of individual features and attributes would be useful to assure the user does try to enter or modify data which cannot be saved.

  • The face should ask for credentials again when the token was not available or is no longer valid. Specifically when a GeomajasSecurityException is received which code ExceptionCode.CREDENTIALS_MISSING_OR_INVALID.

Different modules have different impacts and different purposes. Therefore different categories of modules are required. Geomajas has defined the following set of module categories (matching the directories in the source):

  • application: working examples of applications using the Geomajas GIS framework.

  • backend : these are essential Geomajas modules. Each Geomajas application needs these modules. However, you also need some extensions and layer models or you won't be able to do much.

  • build-tools : some modules which are useful for starting or building Geomajas or a Geomajas project.

  • documentation : documentation modules, specifically the different Geomajas guides.

  • face : faces that present a certain Geomajas client interface to the user.

  • plugin : modules that extend Geomajas. This can either add new functionality, add support for a certain type of data source, provide a security service or a combination.

  • test : modules which are used for (integration) testing of Geomajas.

Full list of Geomajas modules:








Then there are two main sets of plug-ins which provide extra features.

The layer plug-ins provide access to the actual data which needs to be displayed as part of a maps. There are basically two types of layers, providing either raster data (bitmaps) or vector data. The layers which are provided as part of the normal distribution include

Other plug-ins allow extensions in functionality, either by providing additional commands or extending the rendering pipelines, or provide additional security services.

  • geomajas-command : set of commands which are provided as part of the standard distribution. This is so fundamental to using Geomajas that it is provided as a back-end module.

  • geomajas-plugin-printing : printing extensions for the framework

  • geomajas-plugin-springsecurity : a basic security service which can be configured as part of the Spring configuration and does not use an external source for users or policies, making the security configuration entirely static.

Geomajas leverages the Spring framework for configuration.

In your web.xml file, you need to assure the configuration is made available to the application, and you can indicate which files are used to contain the configuration. Though it is possible to put all configuration information in one file, we recommend splitting your configuration in several files. At least one file per application, possibly split further per client layer configuration, and one file for server-side configuration of each of the layers.

Apart from the servlets (which are specific for each face), your web.xml needs an excerpt similar to the following:


The listener class initialises the application context as needed for Geomajas. It appends the context configuration locations which are specified in the contextConfigLocation context parameter to the list of internal configuration locations and uses these to build the application context. All locations which are specified are read from the class path.

Each configuration file needs the following header:


This defines the most common schemas which are needed. The configuration is built by populating the configuration classes. The configuration classes are split up between client-side and back-end. Only the back-end classes are necessary to configure the back-end, which behaves as a catalog of layers. The client side classes are used to define applications and maps, which are purely client-side concepts in the Geomajas architecture.

The back-end classes exist in the org.geomajas.configuration package and have a class name ending in "Info". These classes are actually used to represent the DTO part of the back-end layers, thereby allowing to transfer information or metadata of these layers to the client.

Configuration is done using the Spring Framework. We will give some notions here, but for a full introduction to Spring, please read the reference documentation http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/.

Each configuration file can contain one or more bean definitions, which correspond to actual Java bean instances. You can set all the properties of the objects using this configuration file. Primitive types can be set directly using a string representation of the value. When the value is another bean, then it can either be defined in-line, or you can use a reference. You can choose whether the referenced bean is defined in the same file or a different one. As long as the bean name is unique, and the location is added in the contextConfigLocation context parameter in the web.xml file, the reference is resolved.

It is possible to define a bean with the same name (or id) more than once. In that case, the last occurrence will be used.

The initial bean which needs to be defined is a bean indicating the client application info .


As you can see, this defines the list of maps for the application. It may (optionally) also define some additional user info and a screen DPI parameter. The DPI refers to the resolution in pixels per inch of your monitor, for a PC its usually 96 (the default) or 72.

There needs to be at least one ClientApplicationInfo bean. The bean name is used when requesting the application info.

The back-end configuration consists of security, transaction and layer configurations, plus any additional configuration that is needed for plug-ins and your application.

To make sure the system can be used, you have to configure the security to allow access. The easiest configuration is to allow access to everybody.


Any other configuration would depend on the available security services. For example, when using the springsecurity plugin, the following could be defined.


Most notable in this example is the inclusion of two security services. The first is provided to allow login and logout ( only ) for everybody. The second defines users and authorizations (only the beginning of the configuration is displayed here).

Spring has support declarative transaction management, which relieves us from the burden of writing our own transaction demarcation and exception handling code. Of course, Spring transaction management has to be hooked up with the transaction definition and life cycle of the underlying data platform (hibernate, JTA, JDBC) . Each data access technology should provide its own implementation of the Spring class PlatformTransactionManager. For many platforms this is already part of the Spring libraries, and for GeoTools we have provided a transaction manager.

Transaction management is typically only needed for editable database layers (although we support and encourage it for read-only layers as well), of which we provide two types: HibernateLayer and GeoToolsLayer. There is currently no support for having multiple platform transaction managers, although configurations with multiple transaction managers should at least theoretically be possible and the subject will be investigated further. In practice this means that you currently must not mix editable Hibernate and GeoTools layers.

For Hibernate layers, the following configuration should be used:


Starting from the top, the following are defined:

  • The data source: this specifies the connection pool type and the connection properties of the database (PostGis in this case)

  • The session factory: this is Hibernate's primary singleton and used by the Hibernate layer to access the session/connection

  • A tag to enable annotation-based transactional behavior, internally used by Geomajas to decide which commands need transaction support

  • The platform transaction manager for Hibernate

For GeoTools layers, the configuration is as follows:


Starting from the top, the following are defined:

  • The data store: this is GeoTools' primary data object and will be referenced in the GeoTools layer. The parameters define the connection properties of the underlying physical medium (PostGis in this case)

  • A tag to enable annotation-based transactional behavior, internally used by Geomajas to decide which commands need transaction support

  • The platform transaction manager for GeoTools

Raster layers are image-based layers which, depending on the type, may be configured to retrieve their images from WMS, Google Maps or OpenStreetMap (tile) servers. All raster layer implementations implement the org.geomajas.layer.RasterLayer interface, which means they provide an accessor for a RasterLayerInfo metadata object. The info object configuration is normally defined in the Spring configuration as part of the entire layer configuration. Depending on the type of layer, extra properties are needed to provide a full configuration.

For all raster layers, you will need to define a raster layer info object to define the back-end configuration for the layer. The exact meaning for some of the fields depend on the actual layer, but most important features include:


The location of the images or tiles is defined by calculating the real width and height (based on the resolution) and "paving" the maximum extent with tiles starting at the origin (x,y) of the extent. If no resolutions are predefined, the tiles are calculated by dividing the maximum extent by successive powers of 2. Make sure the width/height ratio of the maximum extent corresponds to the width/height ratio of the tile.

Make sure your classpath contains the required plug-in. If you are using Maven, add the following dependency to your pom:


A complete WMS layer configuration looks as follows:


As you can see, the bean class refers to the actual layer type: org.geomajas.layer.wms.WmsLayer.

The first property is the layer info object, which describes the metadata common to all raster layers. The following properties are needed for this object:

The layer object contains some extra properties which are specifically tied to the WMS server:


Make sure your classpath contains the required plug-in. If you are using Maven, add the following dependency to your pom:


A complete OpenStreetMap layer configuration looks as follows:


The layer info inner bean has the same general content as usual, with one exception : the dataSourceName property is not necessary in this case. As with the WMS layer, the resolutions have been carefully chosen to match the tile server's resolutions. The tile width and height are implied by the server in this case but since they are required metadata for all raster layers, they should be set to the server's values: 256 x 256.

Make sure your class path contains the required plug-in. If you are using Maven, add the following dependency to your pom:


A complete Google layer configuration looks as follows:



The layer info inner bean has the same general content as usual. There are some simplifications though. There is no need to provide resolutions or tile size (256x256 is always used). The crs should always be set to Mercator ("EPSG:900913").

On the layer, you can set the "satellite" property to choose between using normal display (showing streets) or satellite view (by setting this to "true").

Note

You need to assure that you comply with Google's terms of use (see http://code.google.com/apis/maps/). Some of the things you need to do include adding the Google API code in your application (using a Google API key when not running on localhost), and (from the GWT face, using the GoogleAddon class to assure the copyright notes are displayed on the map.

Vector layers contain homogeneous vectorial features. All vector layer implementations implement the org.geomajas.layer.VectorLayer interface, which means they provide an accessor for a VectorLayerInfo metadata object. The info object configuration is normally defined in the Spring configuration as part of the entire layer configuration. Depending on the type of layer, extra properties are needed to provide a full configuration.

The definition of the actual layer is similar to the definition of a raster layer.

For the layer configuration, you have to create the layer info object.


This defines the details common to both raster and vector layers, like layer id, crs, layer type, max extent (bounding box) etc.

The following table describes the properties of the VectorLayerInfo object:


The feature metadata can be found in the FeatureInfo object. This objects contains the complete feature type description (id, attributes and geometry) as well as the validation rules for the attributes. An example definition of this object is given below:

There is also the definition of the features (featureInfo), and the style which needs to be used for the label. Note that the labelAttributeName refers to the name of an attribute as defined in the feature info.

<bean class="org.geomajas.configuration.FeatureInfo" name="countriesFeatureInfo">
    <property name="dataSourceName" value="country"/>
    <property name="identifier">
        <bean class="org.geomajas.configuration.PrimitiveAttributeInfo">
            <property name="label" value="Id"/>
            <property name="name" value="ID"/>
            <property name="type" value="LONG"/>
        </bean>
    </property>
    <property name="geometryType">
        <bean class="org.geomajas.configuration.GeometryAttributeInfo">
            <property name="name" value="the_geom"/>
            <property name="editable" value="false"/>
        </bean>
    </property>
    <property name="attributes">
        <list>
            <bean class="org.geomajas.configuration.PrimitiveAttributeInfo">
                <property name="label" value="Name"/>
                <property name="name" value="CNTRY_NAME"/>
                <property name="editable" value="true"/>
                <property name="identifying" value="true"/>
                <property name="type" value="STRING"/>
            </bean>
            <bean class="org.geomajas.configuration.PrimitiveAttributeInfo">
                <property name="label" value="UNESCO"/>
                <property name="name" value="UNESCO"/>
                <property name="editable" value="true"/>
                <property name="identifying" value="true"/>
                <property name="type" value="INTEGER"/>
                <property name="validator">
                    <bean class="org.geomajas.configuration.validation.ValidatorInfo">
                       <property name="toolTip" value="Member of UNESCO? (value must be 0 or 1)"/>
                       <property name="errorMessage" value="Invalid value: The value must be either 0 or 1."/>
                       <property name="constraints">
                           <list>
                               <bean class="org.geomajas.configuration.validation.NotNullConstraintInfo"/>
                               <bean class="org.geomajas.configuration.validation.MinConstraintInfo">
                                   <property name="value" value="0"/>
                               </bean>
                               <bean class="org.geomajas.configuration.validation.MaxConstraintInfo">
                                   <property name="value" value="1"/>
                               </bean>
                           </list>
                       </property>
                   </bean>
                </property>
            </bean>
        </list>
    </property>
</bean>

Example 6.15. ShapeInMem layer feature info example


The following table describes the properties of the FeatureInfo object:


Last but not least, you can define one or more style definitions which should be used for rendering of the layer. You can define formulas to determine which style should be used. The first style which passes the formula will be applied for the feature.

We also have to define the features.

 <bean class="org.geomajas.configuration.NamedStyleInfo" name="countriesStyleInfo">
    <property name="featureStyles">
        <list>
            <bean class="org.geomajas.configuration.FeatureStyleInfo">
                <property name="name" value="UNESCO Member"/>
                <property name="formula" value="(UNESCO == 1)"/>
                <property name="fillColor" value="#99AA33"/>
                <property name="fillOpacity" value=".6"/>
                <property name="strokeColor" value="#99AA33"/>
                <property name="strokeOpacity" value=".3"/>
                <property name="strokeWidth" value="1"/>
            </bean>
            <bean class="org.geomajas.configuration.FeatureStyleInfo">
                <property name="name" value="Other"/>
                <property name="fillColor" value="#99DD22"/>
                <property name="fillOpacity" value=".6"/>
                <property name="strokeColor" value="#99DD22"/>
                <property name="strokeOpacity" value=".3"/>
                <property name="strokeWidth" value="1"/>
                <property name="symbol">
                    <bean class="org.geomajas.configuration.SymbolInfo">
                        <property name="rect">
                            <bean class="org.geomajas.configuration.RectInfo">
                                <property name="w" value="5"/>
                                <property name="h" value="5"/>
                            </bean>
                        </property>
                    </bean>
                </property>
            </bean>
        </list>
    </property>
    <property name="labelStyle">
        <bean class="org.geomajas.configuration.LabelStyleInfo">
            <property name="labelAttributeName" value="CNTRY_NAME"/>
            <property name="fontStyle">
                 <bean class="org.geomajas.configuration.FontStyleInfo">
                    <property name="color" value="#000000" />
                    <property name="opacity" value="1" />
                </bean>
            </property>
            <property name="backgroundStyle">
                <bean class="org.geomajas.configuration.FeatureStyleInfo">
                    <property name="fillColor" value="#FFFFFF"/>
                    <property name="fillOpacity" value="0"/>
                    <property name="strokeColor" value="#000000"/>
                    <property name="strokeOpacity" value="0"/>
                    <property name="strokeWidth" value="1"/>
                </bean>
            </property>
        </bean>
    </property>
</bean>

Example 6.16. ShapeInMem layer style info example


This defines the identifier, geometry object and attributes for the feature.

Attributes can be either primitive attributes or association attributes. Primitive attributes represent primitive Java types as well as some common types like Date and String. The following primitive attribute types are defined: BOOLEAN, SHORT, INTEGER, LONG, FLOAT, DOUBLE, CURRENCY, STRING, DATE, URL and IMGURL. Association attributes represent non-primitive Java types. There are two types of association attributes defined: MANY_TO_ONE and ONE_TO_MANY. These reflect the many-to-one and one-to-many relationships as defined in an entity-relationship model and can only be used in conjunction with the HibernateLayer.

The Hibernate layer is based on the popular Hibernate O/R mapping framework. It uses a special spatial extension of Hibernate, unsurprisingly called Hibernate Spatial. The Hibernate Spatial project has its project website at http://www.hibernatespatial.org. The spatial extensions or dialects (in Hibernate language) allow the definition of spatial types and the execution of spatial queries in a database independent way.

You need to include the following dependencies to make this work. This needs to include the hibernate spatial provider, in this example, PostGis.


A Hibernate layer cannot be defined by configuration only. As in every O/R model, there has to be a mapping between Java classes and tables in the database. In the most simple case there is a one-to-one mapping between a single class and a single spatial table.

The following listing shows the (partial) definition of a Hibernate annotated Java class Road.java that is mapped to a table roads in the database.


The field annotations describe the relation between the fields of the class and the columns in the table. A special annotation @Type with type org.hibernatespatial.GeometryUserType is used to map the geometry field to the the_geom spatial column.

Once the Java class mapping is finished, the actual layer configuration can be made. An example configuration that matches the Road.java class is shown below:


The first property layerInfo is the reference to the VectorLayerInfo object. While it can be defined inline, it has been defined as an outer bean for clarity here.

The featureModel property refers to the internal feature accessor face of the layer. This property will probably be removed as it has no additional configuration parameters for the moment.

The sessionFactory property refers to the Hibernate session factory. This is the same factory that has to be defined by the transaction configuration.

The dateFormat property determines how the layer will convert date values to strings and vice versa.

As already mentioned, the bulk part of the layer's metadata is defined through the VectorLayerInfo object. An example definition of this object is given below:


The feature metadata can be found in the FeatureInfo object. This objects contains the complete feature type description (id, attributes and geometry) as well as the validation rules for the attributes. An example definition of this object is given below:


Apart from a reference to the layer info, you can set the following parameters:


In most cases, you will need to pass data using the parameters property to get a functional GeoTools layer. This would look similar to this:


The names which are valid depend on the GeoTools data store.

To access a WFS server, the following names can be used as parameters.

  • WFSDataStoreFactory:GET_CAPABILITIES_URL : URL for the getCapabilities document on the server instance.

  • WFSDataStoreFactory:PROTOCOL : determine which HTTP command use when requesting WFS functionality. Set this value to "true" for POST, "false" for GET or NULL for AUTO.

  • WFSDataStoreFactory:USERNAME : set the user name which should be used to authenticate the connection. This parameter should not be used without the password parameter.

  • WFSDataStoreFactory:PASSWORD : set the password which should be used to authenticate the connection. This parameter should not be used without the user name parameter.

  • WFSDataStoreFactory:TIMEOUT : specify the connection timeout in milliseconds. This parameter has a default value of 3000ms.

  • WFSDataStoreFactory:BUFFER_SIZE : set the buffer size for the features. This parameter has a default value of 10 features.

  • WFSDataStoreFactory:TRY_GZIP : indicate whether the data store should use gzip compression to transfer data if the server supports it. Default is true.

  • WFSDataStoreFactory:LENIENT : indicate whether the data store should do its best to create features from the provided data even if it does not accurately match the schema. Errors will be logged but the parsing will continue if this is true. Default is false.

You also have to assure the GeoTools WFS data store is added as dependency in your project. When using Maven, you can add the following dependency.


A map is a client side object. The Geomajas back-end works almost exclusively on layers.[1]On the client side however, these layers are combined into maps. In general, the back-end never needs to know which map the layer is displayed in when doing its work. However the back-end does need to know the coordinate reference system which is used.


The layers refers to the client layer info objects, not the server layer info or layer instances.

For the client side, a lot of additional information can be included in the map configuration. This includes information like background colour, styles which should be used for selected points, lines and polygons and whether scale bare or pan buttons should be enabled.


A map typically also contains a tool bar. If you want one, you have to specify the tools it should include.


Obviously the tools themselves need to be defined as well. You can pass some parameters to the tools. An example tool definition look like this.


Note that the tool id and the names of the parameters are interpreted by the client, so it is the client face which defines the possible values.

Last but not least, you can also configure the layer tree component which may be connected to the map.


This defines the tools which are available in the layer tree widget, and the tree of layers (as a node, which can contain a list of nodes etc).

Note that the layers are indicated by referring to the client configuration object.



[1] The only current exception is the printing command which converts maps to PDF document. Clearly this also uses the map configuration.

The full details about the API can be found in the published javadoc, available on the Geomajas site at http://www.geomajas.org/gis-documentation. There you can find the links for the different versions.

The API for the Geomajas back-end is contained in the geomajas-api module. This contains only interfaces, exceptions and data transfer objects. The data transfer objects are classes which only contain getters and setters. The back-end API is divided in the following packages:

  • command : interfaces, services and data transfer objects related with the command extension points.

  • configuration : data transfer objects which are used for defining the configuration in Geomajas.

  • geometry : Geomajas geometry related data transfer objects.

  • global : some general interfaces, annotations and exceptions which are relevant for a combination of several extension points or the entire API.

  • layer : interfaces, services, exceptions, data transfer objects and some internal objects related with the layers and objects in a layer. These include the definition of a layer, tiles, features and feature models.

  • security : interfaces, services and data transfer objects related with the security extension points and security handling.

  • service : utility services provided by Geomajas.

The back-end also contains a module geomajas-api-experimental. This contains some experimental stuff which may be promoted to the supported API when useful, or may be changed or dumped. As this is not part of the API, it may change between revisions.

The commands are all registered in the Spring context. The "registry key" as indicated below is used to retrieve the commands. These are services, so a singleton should be sufficient for this.

The default naming for the keys is derived from the fully qualified class name. This is automatically assigned when the command is in a (sub package of) the "command" package. To determine the bean name, all parent packages of the "command" package are removed. Then the name is simplified. It will end up having "command." as prefix, optionally followed by a package, followed by the name. As there already is a "command" prefix, the "Command" suffix is removed from the name if present. When the resulting name starts or end with the sub package, then that is removed as well. For example the "org.geomajas.command.configuration.GetConfigurationCommand" class will get "command.configuration.Get" as registry key.









SearchByLocationCommand  
Registry key command.SearchByLocation
Module which provides this command geomajas-command
Request object class org.geomajas.command.dto.SearchByLocationRequest
Parameters
  • location : geometry which should be used for the searching.

  • queryType : specify exactly whether to search, possible values are QUERY_INTERSECTS, QUERY_TOUCHES, QUERY_WITHIN or QUERY_CONTAINS.

  • ratio : if queryType is QUERY_INTERSECTS, you can additionally specify what percentage of overlap is enough to be included in the search.

  • layerIds : array of layer ids to search in.

  • searchType : determines whether to stop searching once something in found in one of the layers (in order of course), or whether to continue searching, and include matching features from all layers.

  • crs : the map's coordinate reference system. The location geometry will also be expressed in this crs.

  • buffer : before any calculation is made, it is possible to have the location geometry expanded by a buffer of this width (in crs space).

  • featureIncludes : indication of which data to include in the feature. Possible values (add to combine): 1=attributes, 2=geometry, 4=style, 8=label. Default value is to include everything.

Description This command allows you to search for features, based on geographic location.
Response object class org.geomajas.command.dto.SearchByLocationResponse
Response values
  • featureMap : map with layer ids as key and a list of features as value. Only layers in which features were found are included in the map.

Table 8.9. SearchByLocationCommand


SearchFeaturesCommand  
Registry key command.feature.Search
Module which provides this command geomajas-command
Request object class org.geomajas.command.dto.SearchFeatureRequest
Parameters
  • layerId : id of layer in which features need to be searched.

  • max : maximum number of features to allow in the result. 0 means unlimited.

  • crs : crs which needs to be used for the geometry in the retrieved features.

  • criteria : array of criteria which need to be matched when searching. Each criterion contains the attribute name, the operator (options include "like" and "contains") and the value to compare. Note that the value usually needs to be contained in single quotes.

  • booleanOperator : operator which should be used to combine the different criteria when more than one was specified. Should be either "AND" or "OR". Default value is "AND".

  • filter : an additional layer filter which needs to be applied when searching.

  • featureIncludes : indication of which data to include in the feature. Possible values (add to combine): 1=attributes, 2=geometry, 4=style, 8=label. Default value is to include everything.

Description This command allows you to search for features, based criteria which allow matching on feature attributes. You can specify multiple search criteria and a filter.
Response object class org.geomajas.command.dto.SearchFeatureResponse
Response values
  • layerId : id of the layer which contains the features. Equals the layerId parameter from the request.

  • features : array of features which match the search criteria. Any geometry contained in the features uses the request crs.

Table 8.10. SearchFeatureCommand




A Geomajas command usually consist of three classes, the actual command (which implements the Command interface), and two data transfer objects, one to pass the request parameters (extending CommandRequest, LayerIdCommandRequest or LayerIdsCommandRequest), and one which carries the response (extending CommandResponse).

It is important to assure your request object extends from LayerIdCommandRequest or LayerIdsRequest when one of the parameters is the layer id (or a list thereof). This can be used by the command dispatcher to assure the layer specific (transaction) interceptors are called.

To create a new command we recommend you use a similar package structure as we used in the geomajas-extension-command module. That is to create a "command" package with under that a "dto" package which contains all the request and response objects, and to put the actual commands in sub packages based on some kind of grouping. This helps to automatically determine a sensible command name.

The basic command implementation looks like this:


Note the presence of the "@Component" annotation which assures the command is registered. You could add the name under which the command needs to be registered in the annotation, but when that is omitted, the default command name is derived from the fully qualified class name. In the example given here this results in command name "command.mysuper.DoIt".

The default way to determine the command name assumes there is a package named "command" in the fully qualified name of the implementing class. It will remove everything before that. It will then remove a "Command" suffix if any. Lastly, it will remove duplication between the intermediate package (between "command" and the class name) and the class name itself. Some examples:


You have to include a line in your Spring configuration to scan class files for annotation to make the components available. For the case above, this could be done by including the following XML fragment in one of your Spring configuration files.


The command will be executed using a singleton. The use of object variables is not recommended. Any object variables will be shared amongst all command invocation, which can be coming from multiple threads at the same time.

Note that it is not mandatory to create your own request and response object classes. If you don't require any parameters you can use EmptyCommandRequest as request class. If you only require a layer id, then use LayerIdCommandRequest. If you only return a success code, you could use the SuccessCommandResponse class.

You have to take care that all objects which are referenced by your request and response objects are actually serializable for the faces in which the commands need to be used. For the dojo face this may require the use of the "@Json" annotation to exclude fields. For GWT you have to assure the no-arguments constructor exists and that the class can be compiled by GWT (no Hibernate enhanced classes, no use of "super.clone()",...).

When the commands are included in a separate module, you should assure the sources are available as these are needed for GWT compilation. This can easily be done using the Maven source plugin.


Actually including the sources can then be done using a dependency like the following (this includes the springsecurity module, both the actual code and the sources). You could set "provided" scope on the source dependency to exclude it from the war file. However, this may prevent use of GWT development mode.


Layers allow access to data which needs to be displayed in a map.

For the existing layers, the details about configuring you map to include that layer are included in the configuration section above.

Client-server communication in Geomajas is executed through a series of commands instantiated on the client and executed by the server. In the GWT face, all such commands are executed by org.geomajas.gwt.client.command.GwtCommandDispatcher. This class has one single method for instantiating such commands and handling the result: the execute method.

The command, required by the execute method (GwtCommand), is in fact a wrapper around a CommandRequest object (see architecture), wherein the name of the requested command is found. Each command expects a certain implementation of the CommandRequest and CommandResponse objects. Note that these request and response objects must also be known server-side, and thus will not be packaged within the GWT client packages. As a second parameter for the execute method, a CommandCallback object is required that will execute it's only method on a successful return of a command.

The execution will immediately return a Deferred object, that can be used to add more callback methods, both for successful as for an erroneous result of the command's execution.


As with any GIS framework or application, the most crucial of all entities is the Map. A map is represented by the org.geomajas.gwt.client.widget.MapWidget , but is set up using the standard model-view-controller paradigm. The widget is the actual view of a map, with Painter objects building the display. The user interaction is handled using controllers, represented by the GraphicsController interface. The third aspect, the model, is represented by the org.geomajas.gwt.client.map.MapModel .

The definition of the model behind a map (org.geomajas.gwt.client.map.MapModel ). This object stores all map metadata and layers, and has an extensive arsenal of methods to operate on the layers and the features.

Another aspect of the MapModel is the list of events that it fires. Handlers for the following events can be added to the MapModel:

  • MapModelEvent : this event is fired when the MapModel has been properly initialized. When a MapWidget is added to the HTML page, it automatically triggers an initialization method. This will ask the server to supply it with the correct metadata, so that the MapModel can actually build it's layers, etc. Once this initialization process is done, a MapModelEvent will be fired. Add a org.geomajas.gwt.client.map.event.MapModelHandler to use this.

  • FeatureSelectedEvent : this event is fired every time a feature within one of this model's vector layers is selected. Add a org.geomajas.gwt.client.map.event.FeatureSelectionHandler to use this.

  • FeatureDeselectedEvent : this event is fired every time a feature within one of this model's vector layers is deselected. Add a org.geomajas.gwt.client.map.event.FeatureSelectionHandler to use this.

  • LayerSelectedEvent : this event is fired every time a layer within this model is selected. Add a org.geomajas.gwt.client.map.event.LayerSelectionHandler to use this.

  • LayerDeselectedEvent : this event is fired every time a layer within this model is deselected. Add a org.geomajas.gwt.client.map.event.LayerSelectionHandler to use this.

A work flow in the GWT face determines how editing should be handled. It can consist of several steps, called activities. When a work flow finishes, changes will typically be persisted. The package is: org.geomajas.gwt.client.map.workflow


Activity:

  • execute : this method is called by the encompassing processor to execute the activity.

  • getErrorHandler : get the error handler that is specifically tuned for the activity.

WorkflowErrorHandler:

  • handleError : Executed when an activity throws an exception during execution. The WorkflowProcessor must make sure this method is executed.

WorkflowContext:

  • stopProcess : informs the WorkflowProcessor to stop the processing of activities. It is the WorkflowProcessors responsibility to ask for this, and execute no more activities when "true" is returned.

  • setSeedData : provide some seed information to the context. This is usually provided at the time of work flow kickoff.

WorkflowProcessor:

  • supports : ensure that each activity configured in this process is supported. This method should be called by implemented subclasses for each activity that is part of the process.

  • doActivities : this method kicks off the processing of work flow activities.

  • setActivities : set a list of activities to be executed in the process. This would also be a good time to check if activities are supported.

  • setDefaultErrorHandler : set a default error handler, which is invoked when the activity throws an uncaught exception.

The spatial package (org.geomajas.gwt.client.spatial) contains a collection of math and geometry related classes and utilities to provide all the client-side calculations one should need. If really complex calculations need to be performed, it's best to let the server (probably using JTS) handle it anyway. The root of the package contains the general mathematical definitions of a Vector, Matrix, LineSegment, and so on. It also provides a general math library and the org.geomajas.gwt.client.spatial.WorldViewTransformer.

The WorldViewTransformer in particular can be a very valuable tool. It allows you to transform coordinates, bounding boxes and geometries between the 3 pre-defined spaces (world, view, pan).

Snapping in Geomajas, is handled by a single manager class called the org.geomajas.gwt.client.spatial.snapping.Snapper. It is the main handler for snapping to coordinates. It supports different modes of operation and different algorithms for the actual snapping. The different algorithms to use are defined in the vector layer configuration files, while the modes are defined by the different implementations of the SnappingMode class. Let us first start with the different modes:

  • ALL_GEOMETRIES_EQUAL : this snapping mode considers all geometries equal when it comes to determining where to snap to. Depending on the snapping algorithm used, it will simply consider all nearby geometries.

  • PRIORITY_TO_INTERSECTING_GEOMETRIES : this snapping mode tries to snap to intersecting geometries before trying the general approach. When searching a snapping coordinate for a given point, this mode will first search for intersecting geometries and try to get a snap to that. If no snapping point can be found, it will consider all nearby geometries (like ALL_GEOMETRIES_EQUAL).

The snapping rules themselves are defined in the server-side configuration. Each vector layer can have many snapping rules. For each rule, 3 fields must be filled:

  • layer : the target layer to snap to.

  • distance : the distance over which to snap. This distance must be expressed in the map's coordinate system.

  • type : the snapping algorithm to use. At the moment 2 types of snapping algorithms are supported: to the nearest point (type=1), and to the nearest edge (type=2). For nearest point snapping can only occur to any coordinate which is a end-point for a geometry, for nearest edge that can be any coordinate on the edge of the geometry. Needless to say, the nearest edge requires more calculating power than the nearest point.

Snapping on the map

When a GraphicsController for the map needs to use snapping (i.e. editing controllers), they should extend the org.geomajas.gwt.client.controller.AbstractSnappingController class. This class extends the GraphicsController class (the base class for all Geomajas map controllers), and overwrites the getScreenPosition and getWorldPosition methods to assure the points are snapped. The AbstractSnappingController also supports the on-the-fly activation and deactivation of snapping.

In the GWT face, the main render method can be found in MapWidget. The render method requires three parameters, a paintable object, a target group to paint in and a status. The paintable object is the actual object that needs to be painted. The target group (org.geomajas.gwt.client.widget.MapWidget.RenderGroup) specifies where in the DOM to draw. The usual choices here are the SCREEN or the WORLD groups. The rendering status (org.geomajas.gwt.client.widget.MapWidget.RenderStatus) determines what drawing action to take.

RenderStatus

The render status can be one of the following:

  • ALL : completely render or re-render the paintable object. If the paintable object contains other paintable object, go through them recursively (a map will paint layers, who in turn will paint tiles, ...)

  • UPDATE : update the paintable object in question, but do not update recursively.

  • DELETE : delete the paintable object from the map.

While rendering, the map uses a visitor to visit the paintable objects recursively and search for painters for each object or sub-object. The "ALL" status will paint recursively while the "UPDATE" status will not go deeper then the given paintable object. Of course, if a given paintable object has no recursive paintable objects, then the difference between "ALL" and "UPDATE" is irrelevant.

RenderGroup

The rendergroup that needs to be specified when calling the map's render method, represents the logical place on the map to draw the paintable object. There are four choices, each having a huge impact.

  • WORLD : drawing should be done in world coordinates. World coordinates means that the map coordinate system should be used. The advantage of rendering objects in the world group, is that when the user moves the map around, the objects will move with it.

  • SCREEN : drawing should be done in screen coordinates. Screen coordinates are expressed in pixels, starting from the top left corner of the map. When rendering objects in the screen group they will always appear at a fixed position, even when the user moves the map about.

  • RASTER : drawing should be done in pan coordinates. All raster layers are drawn in this group. In essence this means that the coordinates are expected to have been scaled for the current scale before drawing, and that only the translation still needs to occur. For advanced use only.

  • VECTOR : drawing should be done in pan coordinates. All vector layers, their selection and their labels are drawn in this group. In essence this means that the coordinates are expected to have been scaled for the current scale before drawing, and that only the translation still needs to occur. For advanced use only.

As will be explained in more detail in the "rendering manual", there are 2 ways of drawing on the map: directly using some rendering context, or indirectly using Paintable objects, Painters and the MapWidget's render method (as explained above). When using the direct approach, one has to call the methods of one of the different rendering contexts. A MapWidget contains a MapContext implementation, which in turn contains 3 different contexts:

  • MenuContext : used for keeping details about right mouse clicks. Not used for rendering.

  • ImageContext : used for rendering images in HTML. All raster layers use this context.

  • GraphicsContext : the main vector graphics renderer. Can also render images, but uses SVG or VML to do so. When rendering shapes, circles, rectangle, etc. you will always be using this context.


The GraphicsContext is the main vector drawing context. It has two implementations: one for SVG and one for VML.


Every object that appears on a Geomajas map, has to implement the Paintable interface. This interface marks types of objects that can be painted. For each type/class of paintable object, an accompanying Painter must be defined as well. The painter will ultimately decide exactly how a paintable object should be rendered. The painter will render objects using it's paint method, or delete objects from the map using it's deleteShape method.


  • GraphicsContext : this is the basic drawing interface. Different implementations will draw in different technologies (i.e. SvgGraphicsContext and VmlGraphicsContext). The whole idea of this GraphicsContext and the painters, was inspired by the Java AWT library. This context will draw basic shapes, according to their id. Since we are using web technologies, all implementations (be they SVG or VML) will use DOM elements to create their drawings. Each DOM element in the GraphicsContext DOM tree should have an id and a parent. This combination of id and parent can later be used to update or delete the object.

    In essence, the drawing methods will result in changes in the visuals of the map, and the painters that will call these methods.

  • Paintable : the basic definition of an object that can be painted onto the map. For each Paintable class, an accompanying Painter class must be defined. The Paintable interface has only two methods. The getId method returns the Paintable objects id, which is it's key in the DOM tree within the parent group. While the accept method will be traversed by the PainterVisitor, and is used to have the object passed to the correct Painter, which will draw the object.

  • WorldPaintable : extension of the Paintable interface for objects that support being rendered in world space. This means that it should be possible to transform the object's geometry/location/coordinate/bbox.

  • Painter : A Painter knows how to paint a specific kind of Paintable object. Exactly what class of Paintable objects it can draw, must be made clear by it's getPaintableClassName method. Furthermore, the Painter has two methods to paint or remove Paintable objects on or from the given GraphicsContext. Basically, the Painter translates the fields and parameters of the Paintable object into calls to the GraphicsContext.

  • PainterVisitor : Geomajas uses a visitor algorithm for it's client side rendering process. The MapWidget uses a PainterVisitor to recursively traverse the tree of Paintable objects, calling the accept method on each node.

    Of course this recursive system of searching for the correct Painter, can only work when the PainterVisitor has all the necessary painters registered. When registering a Painter with the MapWidget, it will actually pass it along to this PainterVisitor instance.

    An example of the recursive painting, can be found in the MapModel, which calls the accept methods of it's layers, which call the accept methods of the visible tiles, which contain features.

There are two ways to render objects onto the map. One uses Paintable objects and Painters, the other is by using the GraphicsContext directly. There are still some general notions that one must know before attempting to draw on the map. Since HTML, SVG and VML are all markup languages which use a DOM tree as basic model, rendering basically is the adding and removing of nodes within this tree. As parent nodes have styling information or other attributes that reflect their child nodes, it is very important to add nodes to the correct parent when drawing.

The GraphicsContext reflects this, by requiring a parent object as first parameters in all drawing methods. Associated with every node is an object that represents it. Given this object, the GraphicsContext can find the correct node. When using the GraphicsContext directly, it is important to be aware of the necessity of using the correct parent group when drawing.

This approach uses MapWidget's render method, which requires three parameters: a Paintable object, a target RenderGroup, and a RenderStatus. If you are unfamiliar with these, visit the beginning of this chapter for a detailed description.

Let us start with an example, where we draw a rectangle in screen space (=pixel coordinates). The code would look something like this:

Rectangle rectangle = new Rectangle("myRectangle");
rectangle.setBounds(new Bbox(10, 10, 200, 200));
rectangle.setStyle(new ShapeStyle("#FF0000", .8f, "#0000FF", .6f, 2));

map.render(rectangle, RenderGroup.SCREEN, RenderStatus.ALL);

This code snippet would draw a rectangle (which implements Paintable), called "myRectangle" in screen space (10 pixels from the top, 10 pixels from the left, and with a width and height of both 200), using the defined style (red interior with a blue border). To delete the rectangle again, you would have to do something like this:

map.render(rectangle, RenderGroup.SCREEN, RenderStatus.DELETE);

When more flexibility is required from the rendering system, the map's render method might sometimes not be enough. If for example we want to render more than one object within a specific parent group. The following code snippet shows how to render a specific parent in screen space and then render a circle within this parent group:

// Create a parent group within screen space:
Composite parent = new Composite("myParent");
map.getVectorContext().drawGroup(map.getGroup(RenderGroup.SCREEN), parent);

// Draw a circle at (20, 20) with radius 10 pixels within parent group:
Coordinate pos = new Coordinate(20, 20);
ShapeStyle style = new ShapeStyle("#FF0000", .8f, "#0000FF", .6f, 2);
map.getVectorContext().drawCircle(parent, "myCircle", pos, 10, style);

Since no special parameters are added to the "myParent" node, the circle is drawn as if it were in the screen group itself. But thanks to the extra parent group, we now have the ability for apply specific styling or transformations on that parent group, and thus altering all children within it. Let us for example move the circle 100 pixels to the right:

// Translate the parent group 100 pixels to the right:
Matrix m = new Matrix(1, 0, 0, 1, 100, 0);
map.getVectorContext().drawGroup(map.getGroup(RenderGroup.SCREEN), parent, m);

Warning

Do not try to render objects in world space by directly accessing the GraphicsContext. Behind the screens of the MapWidget, the world space objects are actually transformed and rendered in vector space. This is done to avoid scaling in the DOM tree (as this is not possible cross browsers).

This section covers the many interfaces regarding buttons, menu items and such that make up the user interface. The specific Geomajas widgets (i.e. LayerTree) require a specific way of doing things. We will cover the interfaces for the Toolbar, LayerTree, map controllers and context menus.

  • Toolbar : the tool bar has two types of default actions one can add to it (there is always the addChild method, which can add any widget, but we are now talking about Geomajas specific possibilities): the ToolbarAction and the ToolbarModalAction. The ToolbarAction is used for actions that need immediate response upon clicking, while the ToolbarModalAction is used for enabling or disabling a certain state.

  • LayerTree : the LayerTree has the possibility to add buttons to it's tool bar that usually act upon the selected layer within the LayerTree. Again two types of actions can be added: the LayerTreeAction and the LayerTreeModalAction. The same difference as with the tool bar applies: the LayerTreeAction is a base abstract class for actions that execute immediately upon clicking, while the LayerTreeModalAction is used for enabling or disabling a certain state (for example: toggle the layer's visibility).

  • Menu : each item in a context menu should extend the MenuAction base class. This is your basic starting point for easily creating new menu items or context menu items.

  • Controllers on the map : for controllers listening to mouse events on a map, there is the GraphicsController interface, or an abstraction under the name of AbstractGraphicsController.

Note

For buttons in the Toolbar or LayerTree it is possible to add them to the org.geomajas.gwt.client.action.toolbar.ToolbarRegistry or org.geomajas.gwt.client.action.layertree.LayerTreeRegistry upon application startup (before MapWidget initialisation!). This allows you to add new buttons which can be included in the map configuration.

The ToolbarModalAction is the basic template for creating selectable tool bar buttons. Usually they enable and disable a certain state on the map when selected or deselected. Many of the implementations that come with Geomajas set a new controller on the map when they are selected.

Note that only one of these ToolbarModalActions can be selected at any given time. In that sense they act as radio buttons.

ToolbarModalAction classes need to be registered in the ToolbarRegistry class. This allows you to get an instance of the widget to put in the tool bar. The tools which are always part of the GWT face are statically defined in the class. Other tools can be added (or overwritten) at runtime before the map is initialised.

When a ToolbarAction is configurable, it should implement the ConfigurableAction interface. This contains a configure() method which will be called for each of the parameters which are defined in the tool configuration.


The LayerTreeAction is your basic abstract class for building layer tree buttons that are executed immediately when clicked. The onClick() method needs to be implemented and it also requires you to specify an icon, a tool tip and a disabled icon. Note that the onClick() has the selected layer within the LayerTree as a parameter.

LayerTreeAction classes need to be registered in the LayerTreeRegistry class. The tools which are always part of the GWT face are statically defined in the class. Other tools can be added (or overwritten) at runtime before the map is initialised.


For interactive mouse listeners on the map there is a general interface, GraphicsController. To write a custom controller, you should always extend AbstractGraphicsController.

Caution

The GraphicsController interface does NOT use SmartGWT events as they provide no way of getting the target DOM element from the mouse events. So the list of handlers that the GraphicsController extends, are all basic GWT event handlers. A separate widget (GraphicsWidget) has been created to catch the events, while the normal MapWidget (which encapsulates the GraphicsWidget) can still handle SmartGWT events.

On top of all the event handling methods that come from the different handlers, the interface also has onActivate() and an onDeactivate() methods. The onActivate() is called before the controller is actually applied on the GraphicsWidget. This is usually used to apply a new context menu on the map and such. The onDeactivate() method is called when the controller is removed from the GraphicsWidget. This is usually used for cleaning up.


You should never directly implement GraphicsController (not that it does not have the "@UserImplemented" annotation), you should always extend AbstractGraphicsController. This abstract class implements all methods as empty methods so you don't have to clutter your code with empty methods (often only a few of the mouse event methods are actually used). It also has some extra methods for return useful information for the mouse events, such as the position (expressed in screen coordinates) or the target DOM element.

Small extract from the AbstractGraphicsController class:


Now that you have your controller you can set it;

mapWidget.setController(new MeasureDistanceController(mapWidget));

Note

There are more abstractions than just the AbstractGraphicsController:

  • AbstractRectangleController : abstract controller that handles drawing a rectangle by dragging the mouse on the map.

  • AbstractSnappingController : abstract controller that allows snapping to be enabled and disabled. When enabled, the returned points when asking getPosition(), are snapped (depending on the configured snapping rules).

This second chapter of the GWT face describes all the widgets that Geomajas has added on top of the SmartGWT widget list. Each widget will be handled in detail so that developers might get a better understanding of what they are here for, and how to use them. Know that many of these widgets are closely connected, either through configuration or coding.

The main map for any Geomajas application using the GWT face. This widget controls the MapModel, the MapView objects, has an internal GraphicsWidget for the actual rendering, and much more. Being the most central of all widget, the MapWidget has quite a few responsibilities and options.

Map - initialization

A first responsibility of the map is the correct initialization of it's model and all layers from the configuration. When the MapWidget is added to the HTML (onDraw), it will automatically fetch the configuration from the server, and than initialize itself (more precisely, build the MapModel). When this is done, the MapModel will fire a MapModelEvent. Many other widgets wait for this moment to initialize themselves, as they often require the MapModel's contents.

View - rendering

A second responsibility lies in the ability to render shapes. The render() method uses a PainterVisitor to recursively go through Paintable objects and look for the correct Painter. All Painter definitions must be registered in the MapWidget, by means of the registerPainter() and unregisterPainter() methods. Also the full list of WorldPaintables is stored within the MapWidget. For more information regarding the rendering, using the render method, visit the rendering manual .

As an addition of the Paintable objects in screen-space, the definition of a MapAddon has been created as well. MapAddons are self regulating pieces of software that are visible at a certain location on the map (in screen space!), and optionally have attached behaviour. Examples are the Navigation buttons and the scale bar.

Controller

To add interactivity to a map, you can add two types of controllers: the GraphicsController and the GWT MouseWheelHandler. For both it is possible to apply a single instance using the setController() and setMouseWheelController() methods.

Options

On top of the previous list of responsibilities, the map also has a few options that allow certain functionality to be present or not. The following options are standard:

  • navigationAddonEnabled : this option can be configured from within the configuration, and determines whether or not the navigation MapAddon is visible. This MapAddon is placed in the upper left corner of the map and allows the user to pan, zoom in and out, and zoom to maximum extent.

  • scaleBarEnabled : this option can be configured from within the configuration, and determines whether or not the scale bar is visible. This shows you the scale of the map by means of a bar of certain length, expressed in the preferred unit type (metric versus English).

  • zoomOnScrollEnabled : this option determines whether or not the ZoomOnScrollController is active by default. This allows zooming in and out on the map using the mouse wheel.


The Geomajas tool bar is an extension of the SmartGWT ToolStrip widget, and allows for many different widgets to be added to it. A tool bar must be initialized with an instance of the MapWidget it is related to. When the MapWidget has successfully initialized itself, it's MapModel will fire the MapModelEvent saying so. The tool bar reacts on this event by searching in the map configuration for the correct list of tool bar buttons. The map configuration can contain tool ids to indicate the tools which need to be added, together with optional parameters. Using the ToolbarRegistry, which contains the mappings between these ids and the relevant ToolbarAction or ToolbarModalAction classes, the tool bar will initialize itself (for more info; see User Interaction).

Existing tools which can be defined include:

  • EditMode : a ToolbarModalAction for editing on the map. Allows the user to create new objects in the selected layer, and allows updating and deleting of selected objects.

  • MeasureDistanceMode : a ToolbarModalAction which allows the user to measure distances on the map.

  • SelectionMode : allow selecting features either by clicking on them, or by dragging a rectangle, thus selecting the features which are inside the rectangle. You need an active (vector) layer for the selection to work. The right click menu allows clearing the selected features and toggling selection at the current position. Press shift or control while selecting to add the selection to the previously selected features. Possible parameters:

    • clickTimeout : when the button it released in less than the number of milliseconds specified here, then the selection is treated as a click. When it takes longer, it is treated as dragging. Default is "500" (ms).

    • coverageRatio : ratio of the feature which needs to be inside the selected area for the feature to be selected. When this is "1.0" then the entire feature needs to be inside the selection rectangle. Default is "0.7".

    • priorityToSelectedLayer : when this is "true" selection will first check the selected layer, and use default behaviour only if nothing is found in that layer. Default behaviour is to try all visible layers, from front to back.

    • pixelTolerance : number of pixels of tolerance allowed when trying to select features.

  • ZoomIn : zoom in to the map at the location clicked (will be centered), using the zoom factor which is configured.

    • delta : zoom in factor, should be >1 to effectively zoom in.

  • ZoomOut : zoom out of the map at the location clicked (will be centered), using the zoom factor which is configured.

    • delta : zoom in factor, should be in the ]0,1[ range to effectively zoom out

  • PanMode : this action allows you to pan the screen by dragging. When keeping either the shift or control key down, it is also possible to indicate an area to zoom into (like ZoomToRectangleMode ).

  • ZoomToRectangleMode : you can indicate a rectangle (by dragging) and it will zoom to make the selected area as big as possible while still entirely inside the map widget.

  • ZoomToSelection : first select some items on the map. After clicking on the the zoomToSelection button the map will be zoomed so that all selected items will fit nicely on the screen.

  • panToSelection : first select some items on the map. After clicking on the panToSelection button the map will be panned in such a way that the center of the selected items is in the center of the screen.

  • ZoomPrevious : go back to the previous zoom level (and location).

  • ZoomNext : go forward again, cancelling a click on ZoomPrevious .


This widget represents a view on the map model which is focused on layers. You see the map layers in a tree, just as they are configured. Accompanied with this view, there are buttons that define certain actions on these layers. Originally there are no buttons in this widget, so they have to be added manually or through configuration. These buttons can either be single actions or selectable buttons (similar to the Toolbar widget - see User Interaction).

Just like the tool bar, the LayerTree waits for the MapModel to be initialized, and also reacts to the MapModelEvent. The layer tree configuration is contained in the map configuration. When the MapModelEvent is fired, the LayerTree will read configuration to know the layer tree structure, which buttons to include,...

Below you see a screen shot of a simple LayerTree where no layer has been selected (and thus all the buttons are disabled):


Once a layer is selected, the LayerTree will ask all buttons whether they should be enabled for that layer. For example, the org.geomajas.gwt.client.action.layertree.LabelAction, which toggles a layer's labels, is only applicable on vector layers, so if the selected layer is a raster layer, that button will remain disabled. The same LayerTree with a selected layer looks like this:


The LayerTree has few public methods, but it does quite a lot behind the screen. The tree is a SmartGWT TreeGrid, where the LayerTree adds handlers to the nodes and leaves (using LeafClickHandler and FolderClickHandler), which trigger layer selection in the MapModel. The LayerTree also listens to layer selection events, to adjust it's own appearance. For example, when a layer is selected, the proper node has to be selected and all the buttons updated.

The LayerTreeAction and LayerTreeModalAction are also specifically designed to cope with the different stages that they should be able to display. The LayerTreeModalAction can be disabled, enabled and selected or enabled and deselected. For each it is imperative that clear markings are given. This means that different icons are usually used for the different stages. These different icons should be given to the actions at construction time.

Currently the following actions are defined:

  • org.geomajas.gwt.client.action.layertree.VisibleAction : a LayerTreeModalAction that switches the visible flag on the selected layer.

  • org.geomajas.gwt.client.action.layertree.LabelAction : a LayerTreeModalAction that switches the display of labels for the selected layer.

  • org.geomajas.gwt.client.action.layertree.LayerRefreshAction : a LayerTreeAction that refreshes the selected layer on click.

The FeatureListGrid is a table listing the attributes of features within a single vector layer. Each feature is represented by a row in the grid, with at the top a header that shows the attribute label, as configured in the configuration. As only vector layers can contain features, the grid will be empty for raster layers.

The FeatureListGrid has a few options that determine it's behaviour and appearance:

  • selectionEnabled : enables or disables selection of features when selecting a row in the table. When this is enabled, the table will keep feature selection consistent with the map model. If the user selects a row, the feature will also be selected on the map.

  • allAttributesDisplayed : show all attributes (true) or only the 'identifying' attributes (false)? Attributes can be configured as "identifying" in the configuration. This difference allows for a select list of attributes to be visible in the grid, keeping overview. The user can always ask more details by double clicking the line.

  • editingEnabled : determines whether or not editing the attributes is allowed. When double clicking a row in the table, a FeatureAttributeWindow will appear, containing the feature of the selected row. This setting determines if that window allows editing or not.

  • idInTable : show the feature's id in the table. This is false by default, and should not really be necessary.

This table is an extension of the SmartGWT ListGrid widget. It automatically has grouping, filtering and sorting abilities (and much more...). The FeatureListGrid makes it possible to easily display features. You have to set the layer from which to display features. Then you can add features one by one. If no layer is set, then then "addFeature" method will not add any rows to the table. Setting the layer will automatically create the grid header, using the layer's attribute definitions.


For the dojo face to function properly, it is important that your web.xml contains the references to the necessary information and servlets. Let's dissect an example web.xml file.


The file starts with the reference and configuration of the Geomajas context listener. This assures the application configuration is available for Geomajas and indicates the location of the additional configuration files.


Next up is the definition of the actual servlets which are needed. The order in which they need to be initialised is also specified.

  • PdfServlet: this is used to produce printable maps in PDF format.

  • JsonServlet: the servlet which allows you to execute commands by sending the request as JSON and which returns the result as JSON as well.

  • ResourceServlet: this allows you to get the Geomajas and dojo script files assuring that they are properly cached and gzip compressed.


To finish, the servlet mappings need to be defined. You don't really have a lot of choice here, as the client side JavaScript expects these values.

In many cases you also want to do some client side configurations. This can be done in one of two ways.

You can include a "geomajas-constants.js" file in your code (the name of the file can differ).


You can override some configurations in your html file, on the script tags in head..


For simple applications which don't have any custom JavaScript code, the dojo-simple project layout with only one module is recommended. Anything more advanced is better of using the project layout of the dojo-example project. This allows using dojo's shrinked builds which combine all JavaScript in one large cachable file, thus optimizing load time. As this shrinking processes has a massive impact on project build time (and makes the code difficult to debug), you want to be able to test without this skrinking step. This is tackled using the multi-module project. It has the following sub-projects :


As opposed to the conventional practice of putting JavaScript directly in the war project, our module concept requires you to put this code in a separate jar project. This jar will be added to the web application as a normal java library and the JavaScript files in it will be served from the class path by the ResourceServlet. The appropriate mapping should be added to the web.xml:


By structuring JavaScript code as jar artifacts, our Maven dojo plug-in is capable of making this code accessible to the browser by importing a single dojo layer script in the web page. If the name of the layer is example , the import statements will be:


As you can see, some configuration parameters can be passed by adding a geomajasConfig attribute to the script tag, exactly like dojo does with djConfig. The above import statements will be exactly the same for the compressed or uncompressed version of the layer. While the compressed version contains all necessary code in a single file (using the dojo custom build facility), the uncompressed version is just a set of dojo.require(...) statements, one for each module.

Our Maven dojo plug-in has two different configurations, depending on whether the custom build should be applied or not. The two different configurations have been applied in the geomajas-dojo-example-modules-shrinksafe and geomajas-dojo-example-modules projects, respectively. By defining a Maven dependency in geomajas-dojo-example-modules-war on one or the other, the compressed or uncompressed version of the JavaScript libraries is used. The switch between the two options is managed by a Maven profile in the parent project (geomajas-dojo-example). This should be passed in the Maven build command:

  • compressed/shrinked build: mvn install

  • uncompressed build: mvn -Pnoshrink install

The Maven dojo plug-in is capable of executing a custom dojo build from within Maven. This essentially collects and/or compresses (using shrinksafe) JavaScript modules that have been bundled as jar artifacts.

A typical configuration looks as follows:


The plug-in has the following goals:

  • collect: generates a dojo layer script with the necessary dojo.require() statements to import all the modules

  • build: generates a compressed version (shrinksafe) of the dojo layer script

The following parameters can be configured:


The output of the plug-in consists of generated JavaScript files. The precise output dependens on the goal. If the goal is "collect", it is a single file. If the goal is "build", it contains the complete contents of the release directory of the dojo build. In all cases, the JavaScript output is generated in the folder <projectdir>/target/generated-resources/dojo, which is added as a resource folder to the Maven project.

  • The LayerModel class has been integrated in VectorLayer. This modifies the configuration. Where before you would have written

    <bean name="countriesModel" class="org.geomajas.layermodel.shapeinmem.ShapeInMemLayer">
        <property name="url" value="classpath:shapes/africa/country.shp"/>
    </bean>
    <bean name="countries" class="org.geomajas.internal.layer.layertree.DefaultVectorLayer" >
        <property name="layerInfo" ref="countriesInfo" />
        <property name="layerModel" ref="countriesModel" />
    </bean>

    into

    <bean name="countries" class="org.geomajas.layer.shapeinmem.ShapeInMemLayer">
        <property name="layerInfo" ref="countriesInfo" />
        <property name="url" value="classpath:shapes/africa/country.shp"/>
    </bean>

    Note that this includes changing "layermodel" to "layer" in all module and package names.

  • FeaturePainter interface and related stuff has been removed. These are obsolete with the introduction of the VectorLayerService.

  • GeotoolsLayer has been renamed GeoToolsLayer.

  • With the change in directory structure, the commands have moved from the org.geomajas.extension.command package to org.geomajas.command. The LogCommand has also been moved into the general sub-package.

  • Security constraints are now applied in Geomajas. By default, nothing is authorized, so you always have to configure at least one security service. To go back to the old (allow-all) behaviour, include the following excerpt in your configuration file.

    <bean name="security.securityInfo" class="org.geomajas.security.SecurityInfo">
        <property name="loopAllServices" value="false"/>
        <property name="securityServices">
            <list>
                <bean class="org.geomajas.security.allowall.AllowAllSecurityService"/>
            </list>
        </property>
    </bean>
  • Layers are now more sensitive to the attributes which are defined for the layer. Attributes which have not been defined in the feature info are not accessible this is the result of the refactoring where the InternalFeature store attributes as Attribute objects).

The configuration API has been split up in a back-end part and a client (or faces) part. The following general rules have been kept in mind:

  • Back-end configuration should be restricted to those properties that are functionally needed on the back-end. We essentially regard the back-end as a container of layers or, in WFS terms, feature types. Higher level concepts like map or application should be dealt with at the client (or faces) level.

  • Client configuration should not impact the back-end state. In the near future, this will make it possible to reconfigure clients without restarting the server.

The configuration API has profoundly changed. Where possible, the back-end classes have retained their original (before the split) names, after pruning them to remove all client related information. The client classes have been mostly created from scratch and have been named ClientXxxInfo.java for consistency. They have been located in a separate package, called org.geomajas.configuration.client.The following table gives a top-down overview of the back-end configuration classes (new classes and properties have been marked in bold ):


The most important changes are:

  • The removal of client-side properties like visible, label, viewScaleMin, viewScaleMax, style and snapping rules. These are moved to the client configuration (see hereafter).

  • The replacement of the single style definition list by a set of named styles. These are styles that are preconfigured in the back end.

  • Inclusion of the label attribute name and style as part of the named style. This is more logical and in line with the SLD (Styled Layer Descriptor) specification.

The client or face classes are largely new and have been relocated to the org.geomajas.configuration.client package. The following table gives a top-down overview of the back-end configuration classes (new classes and properties have been marked in bold ):


Apart from these changes in content, some general technical improvements have been made as well:

  • The Spring bean name (or id) is used to set the id property of the class if there is one. This makes it unnecessary to define the id separately. The way this is done is by using a Spring BeanPostProcessor. (see org.geomajas.internal.configuration.ConfigurationBeanPostProcessor)

  • Some calculations that were previously done in the GetConfigurationCommand are now done in the ConfigurationBeanPostProcessor.

  • Cloning of the client configuration classes can be done with general deep cloning techniques like serialization, bypassing the need for custom cloneable implementations.

As usual, example configurations can be found in the application projects.