Geomajas Community Documentation

Geomajas user guide for developers

Geomajas Developers and Geosparc

v1.7.1


I. Introduction
1. Preface
1.1. About this document
1.2. About this project
1.3. License information
1.4. Author information
II. Architecture
2. Architecture
2.1. Command
2.2. Pipelines
2.2.1. Pipeline architecture
2.2.2. Application in the back-end
2.3. Layer
2.4. Security
2.4.1. Security architecture
2.4.2. How is this applied ?
2.4.3. Server configuration
3. Plug-ins
4. Project structure
4.1. Face and plug-in registration
4.2. Module Overview
III. API
5. API contract
5.1. API annotation
5.2. Back-end API
5.3. Command and plug-in API
5.4. GWT face API
5.5. API compatibility and Geomajas versions
6. Commands
6.1. CommandDispatcher service
6.2. Provided commands
7. Layers
7.1. RasterLayerService
7.2. VectorLayerService
8. Security
8.1. Authentication versus authorization
8.2. What can be authorized
8.3. SecurityManager service
8.4. SecurityContext service
9. Pipelines
9.1. PipelineService
9.2. Configuration
9.3. Default pipelines
9.3.1. RasterLayerService
9.3.2. VectorLayerService
10. Utility Services
10.1. ConfigurationService
10.2. GeoService
10.3. DtoConverterService
10.4. FilterService
10.5. TextService
IV. Configuration
11. Configuration basics
11.1. web.xml
11.2. General principles
11.3. Geomajas configuration
12. Map configuration
12.1. Raster layer configuration
12.1.1. Raster layer info
12.2. Vector layer configuration
12.2.1. Vector layer info
12.2.2. Bean layer configuration
12.3. Client configuration
12.3.1. Map configuration
12.3.2. Client layer configuration
13. Security configuration
14. Transaction configuration
15. Coordinate Reference Systems
V. How-to
16. Writing your own commands
17. Create a plug-in
17.1. Using the plug-in archetype
17.2. Plug-in structure
17.3. Plug-in declaration and dependencies
18. Create a layer plug-in
18.1. Writing your own layer
19. Create a security plug-in
19.1. Writing your own security service
VI. Appendices
A. Migrating between Geomajas versions
A.1. Migrating between Geomajas 1.6.0 and Geomajas (back-end core) 1.7.1
A.2. Migrating from Geomajas 1.5.4 to Geomajas 1.6.0
A.3. Migrating from Geomajas 1.5.3 to Geomajas 1.5.4
A.4. Migrating from Geomajas 1.5.2 to Geomajas 1.5.3
A.4.1. General API changes
A.4.2. Configuration changes
A.5. Migrating from Geomajas 1.5.1 to Geomajas 1.5.2
A.6. Migrating from Geomajas 1.5.0 to Geomajas 1.5.1
A.7. Migrating from Geomajas 1.4.x to 1.5.0

Copyright © 2009-2010 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 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 built from many services which are wired together using dependency injection (DI). This wiring is partly done automatically, and partly through the configuration files. Thanks to the inversion of control (IoC) the back-end is very flexible and can be customized at will.

The client-server communication is done through the command dispatcher. This delegates to one of the action based services which handle the command. These typically interact with one or more of the topic based services (though the command could also handle everything directly). The most important built-in topic based services are the raster and vector layer service. They are used to access the GIS data which is stored as either raster or vector layer.

All the services are running in a secured zone and will typically interact with the security context to verify access rights (or policies).

The layers access the actual GIS data, either directly or using some kind of transformation service (for example a GeoServer or MapServer instance).


With this advanced configuration, many integration options exist. One example is displayed above, the inclusion of Geomajas in an existing application. On the client side, you just have to include the map widget in your web application. On the server side, there are many options, but you could for example assure that the transactions are shared between your existing application and Geomajas.


As is the case for most powerful frameworks, Geomajas stands on the shoulder of giants. We use some of the major open source libraries in our framework (and we integrate with a lot more).


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.

Pipelines can be extended. When a pipeline is defined, it is possible to include hooks for extensions. These are special no-op steps. When a pipeline is defined, your can either define all the pipeline steps, or refer to a delegate pipeline combined with a map of extension steps. The pipeline will then be based on the delegate pipeline with the extensions steps added after the hooks with matching names.

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.

Geomajas provides a basic set of functionality as part of the back-end core. This can be extended and made available using plug-ins. One of the functions of the back-end core is to act as a plug-in container. Plug-ins are optional libraries that extend the core functionality by taking advantage of the public API. There are three special types of plug-ins, faces, layers and security plug-ins. which provide extra features, faces, layers and other plu

Faces provide external interfaces for Geomajas. These give access to users or external systems to the configured data. The faces which are included in the Geomajas project are

  • GWT face : our recommended face for displaying and editing GIS data in the browser. This allows you to build your web user interface in Java.

  • dojo face : a face which allows web display and editing using dojo toolkit. The user interface needs to be developed using JavaScript.

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 they 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-staticsecurity : 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.

The back-end also contains a set of spatial services. These include services for accessing raster and vector services and a set of utility services.

The project is built from a large set of modules. A specific application can choose which modules are used or not. In principle, the back-end module are always required and at least one face and at least one layer plug-in. More plug-ins or faces can be added as needed.

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 a face and some plug-ins (like layers) 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. These are the general guides, each of the plug-ins also has a documentation module.

  • 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:








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.feature.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 6.10. 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 6.11. SearchFeatureCommand




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 map configuration chapter.

Vector layers and the data contained within are accessible using the vector layer service. You should not try to access the layers directly. This service assures that the security constraints are adhered. Following access methods are available

  • void saveOrUpdate(String layerId, CoordinateReferenceSystem crs, List<InternalFeature> oldFeatures, List<InternalFeature> newFeatures) throws GeomajasException : allows creating or updating several features. You have to pass both the old features (null or the feature before it was modified) and the new value of the feature. The two are at compared to determine whether to create, update or delete.

  • List<InternalFeature> getFeatures(String layerId, CoordinateReferenceSystem crs, Filter filter, NamedStyleInfo style, int featureIncludes) throws GeomajasException : read all features from the layer which match the filter. You can specify which aspects of the feature need to be set.

  • List<InternalFeature> getFeatures(String layerId, CoordinateReferenceSystem crs, Filter filter, NamedStyleInfo style, int featureIncludes, int offset, int maxResultSize) throws GeomajasException : read a batch of features from the layer which match the filter. You can specify which aspects of the feature need to be set..

  • Envelope getBounds(String layerId, CoordinateReferenceSystem crs, Filter filter) throws GeomajasException : get the bounds of the visible features which match the filter. This can be useful for fit-to-page like functionality.

  • List<Attribute<?>> getAttributes(String layerId, String attributeName, Filter filter) throws GeomajasException : get the list of possible attribute values.

  • InternalTile getTile(TileMetadata tileMetadata) throws GeomajasException : get a vector tile.

Geomajas has security built-in. If you don't provide a security configuration, nothing will be authorized. For unsecured access, you can add


which will allow all access to everybody, including full access to features which are only partly within configured bounds.

It is also possible to configure other security services, to allow authentication and authorization to be done by the services which are configured.

Note

When configuring security services, it is important to assure that login is possible. Anything which is not explicitly allowed in not allowed, which likely includes the command which is used to login. You have to make sure that everybody can access the login command.

Specific configuration depends on the configured security services, details of which can be found in the specific plugin's documentation.

Pipelines are building blocks which are used in Geomajas to make certain aspects highly extend- and customizable. For more details, see the architecture Section 2.2, “Pipelines”.


A pipeline can be defined by specifying the pipeline name and the pipeline steps.


A pipeline can be layer specific and can refer to a delegate (bean reference). The use of the delegate means that the pipeline definition (list of steps) is copied from the delegate.


When referring to the pipeline definition using a delegate, the pipeline can also be extended by inserting additional steps at the extension hooks. You can pass a map of "extensions" which are named steps. When a extension hook of the name is found, that step will be included in the pipeline just after the hook definition.


The default pipelines are detailed here. All the steps mentioned here have a hook before and after the step to allow customization of the pipeline. These hooks have the name of the step as mentioned here, with either "pre" or "post" as prefix (note that these keys are case dependent).

The Geomajas back-end core also contains a set of utility services.

Geomajas leverages the Spring framework for configuration. The initial configuration needs to be done using web.xml. There you need to indicate the files which contain the configuration information.

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.

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. When no location is specified, the files is searched on the class path. You can also use location prefixes as defined by Spring. To allow use of configuration file on the web context, use an empty location (just a colon as prefix, eg ":/WEB-INF/config.xml"). Note that whitespace is used as separator which means that the path itself should not contain spaces.

These are defined using an excepts like the following:


You also need to define at least the dispatcher servlet and possible an additional servlet for your faces. The dispatcher servlet can be defined as follows.


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 have a class name ending in "Info" and are mostly found in the org.geomajas.configuration package. 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 central configuration which needs to be done is the map and the collection of layers which are part of that map.

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:

Name Description
dataSourceName The name of the data source as used by the layer.
crs The coordinate reference system, expressed as "EPSG:<srid>". Caveat: make sure this is the same as the maps' crs as full raster image reprojection is not supported! If the crs is not the same, an attempt will be done to rescale and align the center coordinates, though.
maxExtent The bounds of the layer, specified in layer coordinates. After transformation to map coordinates, this determines the locations and absolute size of the tiles.
zoomLevels

A list of scale values corresponding to the zoom levels at which the raster data should be fetched.

An image or tile scale is obtained by dividing the size of the tile in pixels by the size of the tile in map units. For example, if the tile is 256 x 256 pixels and this corresponds to an area of 100 m x 100 m, the scale can be calculated as 256/100 = 2,56 pixels per meter.The inverse value of the scale is more often used and is sometimes called the resolution . Images are usually optimized or prerendered for a specific (set of) resolution(s), so it is important to specify these here if they are known. On top of that, some servers provide specific tile caching for these predefined resolutions (for example WMS-T).

A word of caution concerning zoom levels : setting the zoom levels here will only make sure that tiles will be fetched at predefined levels but does not impose any restrictions on the zoom levels of the map itself. If the zoom levels of the map have different values or are not specified at all (arbitrary zooming), raster images will be stretched on the client side to accomodate for these differences.

tileWidth Width in pixels of the requested images.
tileHeight Height in pixels of the requested images.

Table 12.1. Raster Layer info


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.

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:


The following table describes the properties of the FeatureInfo object:


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.

Last but not least, you can define one or more named style definitions which should be used for rendering of the layer. The actual style that is being used by the client is determined in the client configuration, but you predefine a number of styles (of type NamedStyleInfo) here for later reference in the client configuration.

Each style object is itself composed of a number of feature styles (FeatureStyleinfo) and a label style (LabelStyleInfo). You can define formulas to determine which feature style should be used. The first style whose formula passes will be applied for the feature.



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 crs evidently refers to the map's coordinate reference system. The display unit type determines the unit type of the scale bar (METRIC, ENGLISH or CRS). The initial bounds determine the visible area of the map at startup time. The layers refers to the client layer info objects, not the server layer info or layer instances.

Additionally, a lot of style 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.


An other important aspect of the map is the scale configuration. The scale configuration allows to define a maximum scale beyond which the user is not allowed to zoom in. This is not needed for zooming out as there is always a maximum bounds defined for the map (either explicitly or calculated as the union of the layer bounds). Next to that you can define a list of zoom levels. By default, the map will allow zooming to arbitrary scale levels but you may wish to enforce certain scale or zoom levels upon the user (like Google Maps does). By doing so, continuous zooming will no longer be possible and any zooming action will "snap" to the predefined scale levels.


Scales can be defined in 2 possible notations:

  • the 1 : x notation (see the above listing) is most commonly used in geographics and expresses the ratio between 1 meter on the screen and 1 meter on the earth's sphere

  • the floating point notation (e.g. 0.0001) is used by us to express the number of pixels on the screen that correspond to 1 unit on the map (1 pixel per 10000 map units in our example)

Both scale definitions serve a different purpose. The 1 : x scale should give you an idea of what the true scale is at which the map is shown, although in practice this may depend on the DPI (actually PPI) and pixel size of your device. The floating point scale (which has units of pixel/m or pixel/deegree) is used to precisely define the resolution of raster images on the screen. If you use floating point notation, you can make sure that the scales that are being used in an application are the same as those of the raster layer(s) that lies beneath (see raster layer configuration). Otherwise the raster images may get blurry or unreadable when they need to be resized.

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.

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 staticsecurity 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).

Geomajas uses GeoTools' gt-epsg-wkt module to define the coordinate reference systems which are available.

If you want to add extra coordinate reference systems, this can be done by defining them in the configuration. For example, Geomajas itself already defines the "EPSG:900913" crs (which one of the many codes for the Mercator projection used by Google Maps and OpenStreetMap).


You can add as many of these beans as needed. The keys transformation which are added this way are tested before the GeoTools library, so you can overwrite definitions if needed.

If you don't like the dependency on the gt-epsg-wkt library, then you could exclude this dependency in your maven pom and use a different dependency if needed.

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 staticsecurity 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.

  • ApplicationContextUtils has been renamed to ApplicationContextUtil and is now included in the api (this was done to adhere to the coding style).

  • When building the dojo face and the dojo-example application, the maven "-Pnoshrink" has been replaced by "-DskipSkhrink".

  • The use of the dispatcher servlet was introduced in 1.7.1. It is strongly recommended that you include it in your web.xml file to assure all plug-ins which expect this can function.

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:META-INF/geomajasWebContext.xml</param-value>
            <description>Spring Web-MVC specific (additional) context files.</description>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/d/*</url-pattern>
    </servlet-mapping>
  • the "springsecurity" module has be renamed "staticsecurity" to more correctly address the nature of the plug-in and and to avoid possible confusion with Spring's security stuff. Additionally the old module has been split in two, one part being the back-end/configuration module, and another the gwt module.

  • Many of the layers contain a bug in the 1.6.0 version assuming that injected services are fully initialised (and thus usable) while building the application context. Because of changes in the implementation of some services, these bugs become visible when using the 1.7 backe-end. You have to update your layers as well to 1.7+ to avoid these problems.

  • 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.