Welcome to Planet OSGeo

September 11, 2025

Prezado leitor,

Integrar o GeoServer a um ambiente DevOps permite transformar a publicação e manutenção de dados geoespaciais em um processo automatizado, rastreável e seguro. Com pipelines CI/CD (Continuous Integration / Continuous Deployment), é possível validar, versionar e publicar camadas geoespaciais de forma confiável, garantindo que novas versões de dados e estilos cheguem ao servidor sem intervenção manual.

1. Conceito de CI/CD para GeoServer

O objetivo do CI/CD é automatizar a entrega de software ou dados. No contexto do GeoServer, podemos aplicar CI/CD para:

  • Publicação automática de camadas vetoriais e rasters.
  • Aplicação de estilos (SLD/SE) versionados em repositórios Git.
  • Validação de dados antes do deploy.
  • Rollback automático em caso de falhas.

Combinando REST API do GeoServer e pipelines CI/CD, conseguimos ter controle total sobre a atualização de dados geoespaciais.

2. Estrutura do pipeline DevOps

Um pipeline típico para GeoServer + PostGIS em CI/CD inclui:

  • Repositório Git: versionamento de SLDs, scripts de publicação e, quando aplicável, dados GeoJSON ou shapefiles pequenos.
  • Serviço de CI/CD: GitHub Actions, GitLab CI/CD ou Jenkins para executar scripts de publicação.
  • Servidor GeoServer: alvo do deploy automático, com REST API habilitada e credenciais de acesso seguras.
  • Banco PostGIS: para integração de dados vetoriais, garantindo consistência com o GeoServer.

Visualmente, o fluxo pode ser resumido assim:

Git Repo (dados e SLDs) 
      │
      ▼
CI/CD Pipeline (GitHub Actions / GitLab CI / Jenkins)
      │
      ▼
Scripts de automação → GeoServer REST API
      │
      ▼
Publicação automática de camadas e estilos

3. Exemplo de GitHub Actions para publicar SLDs

Podemos criar um workflow simples que envia estilos ao GeoServer sempre que houver uma atualização no repositório:

name: Deploy GeoServer Styles

on:
  push:
    paths:
      - 'styles/**'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Enviar SLDs para GeoServer
        run: |
          for file in styles/*.sld; do
            curl -u ${{ secrets.GEOSERVER_USER }}:${{ secrets.GEOSERVER_PASS }} \
                 -XPUT -H "Content-type: application/vnd.ogc.sld+xml" \
                 --data-binary @$file \
                 http://localhost:8080/geoserver/rest/workspaces/cite/styles/$(basename $file .sld)
          done

Esse workflow garante que qualquer atualização de estilo seja aplicada automaticamente no GeoServer sem intervenção manual.

4. Automação de publicação de camadas

Além de estilos, podemos publicar camadas vetoriais e rasters via scripts Python ou Bash integrados ao CI/CD:

  • Verificação de novos arquivos em pastas específicas ou repositórios de dados.
  • Validação de CRS, atributos e integridade dos dados.
  • Uso da REST API para criar stores, featureTypes e coverages.

Exemplo rápido em Python para publicar um shapefile:

import requests
import json

GEOSERVER_URL = "http://localhost:8080/geoserver/rest"
AUTH = ("admin", "geoserver")

# Criar ou atualizar store
store_json = {"dataStore": {"name": "biomas_postgis", "connectionParameters":{"entry":[{"@key":"url","$":"file:data/biomas.shp"}]}}}
requests.post(f"{GEOSERVER_URL}/workspaces/cite/datastores", auth=AUTH, headers={"Content-type":"application/json"}, data=json.dumps(store_json))

# Publicar camada
layer_json = {"featureType":{"name":"biomas","title":"Biomas do Brasil","srs":"EPSG:4674"}}
requests.post(f"{GEOSERVER_URL}/workspaces/cite/datastores/biomas_postgis/featuretypes", auth=AUTH, headers={"Content-type":"application/json"}, data=json.dumps(layer_json))

5. Boas práticas em pipelines CI/CD para GeoServer

  • Versionamento de estilos e scripts em Git, permitindo rollback fácil.
  • Testes automáticos antes de publicar novos dados ou estilos.
  • Segurança: use variáveis de ambiente ou secrets para credenciais da API.
  • Monitoramento de logs do GeoServer para detectar erros em tempo real.
  • Divisão de ambientes: dev, staging e produção para evitar impactos em serviços críticos.

Conclusão

Integrar o GeoServer a pipelines DevOps transforma o gerenciamento de dados geoespaciais em um processo confiável, repetível e rastreável. CI/CD permite aplicar estilos, publicar camadas e atualizar dados automaticamente, mantendo serviços WMS e WFS sempre consistentes e disponíveis.

by Fernando Quadro at September 11, 2025 12:00 PM

September 10, 2025

We're on the home stretch now!

The first (and hopefully only) release candidate of MapGuide Open Source 4.0 is now available.

Changes since Beta 3

This release has the following changes since Beta 3:

  • A new .net repository admin tool that replaces the existing series of PHP scripts that required a super-ancient PHP binary.
  • Apache httpd updated to 2.4.65
  • PHP updated to 8.3.25
  • Tomcat updated to 9.0.108
  • Plugged a memory leak in selection processing if it throws an FDO exception
  • The .net bindings now have experimental support for Linux

New nuget packages

As a test run for the final release, the .net bindings have also been published to nuget.
To get started building a .net MapGuide application for 4.0 RC1, install the above packages (ver 4.0.0.10185) via the nuget package manager or via the dotnet CLI.

Need an idea or example of how to build a MapGuide application using these packages in modern asp.net core? Have a look at the mvc core sample.

As already stated, these bindings also have experimental support for Linux, meaning you can publish your .net application to run on Linux as opposed to Windows. Here's a screenshot of the mvc core sample application published to and running on Linux, talking to a MapGuide Server also on Linux being contacted from a web browser on Windows.


MapGuide Portable

The sub-project formerly known as mg-desktop is now known as MapGuide Portable (or mg-portable).

Why the name change? The "desktop" moniker felt too constricting. You're not exclusively tied to building just desktop applications. You could build "headless" console applications or maybe even MapGuide Server-free web applications with this library. As such, "portable" is the better moniker as it is a MapGuide Platform that goes with your application, in effect being portable.

Why are we mentioning MapGuide Portable in a 4.0 RC1 announcement? Because our extensive work on generating API bindings with vanilla SWIG had some minor splash damage. As MapGuide Portable builds on top of the shared Foundation/Geometry/PlatformBase series of libraries, we'd be leaving this in the lurch if we got these new fancy .net bindings for MapGuide proper, but still had to resort to the old crufty legacy bindings for MapGuide Portable, so extra effort was spent to get the .net bindings for MapGuide Portable to not only be generated through vanilla SWIG as well, but also retain package modularity by being able to depend on the new Foundation/Geometry/PlatformBase nuget packages.

The end result is a new series of nuget packages that you can use either in a legacy .net Framework 4.8 WinForms application or a WinForms application in the new modern .net!


Unlike the proper MapGuide API nuget packages, the MapGuide Portable packages are still Windows-only (since WinForms is tied to Windows). The new MapGuide Portable packages are:
The older mg-desktop-* packages on nuget should be considered deprecated and you should move over to these new MapGuide Portable nuget packages as these packages support modern .net while the mg-desktop-* packages can only be used in legacy .net Framework.

The final stretch

Between RC1 and the Final release I will be primarily focusing on an API documentation sweep, getting functional API documentation up and ready. Only bugs of a show-stopping nature will be addressed and only if such bugs have easy means of reproducing (I can only do so much). I am allowing for up to a month for this development window before the Final release, so that we can wrap things up before Windows 10 reaches end of life, just over a month from now.

This long and arduous journey is almost at an end!

by Jackie Ng (noreply@blogger.com) at September 10, 2025 12:41 PM

Prezado leitor,

Monitorar o GeoServer é fundamental para garantir a estabilidade dos serviços e antecipar falhas. A REST API do GeoServer oferece endpoints que permitem criar healthchecks, consultar status de camadas, conexões e até acompanhar logs em tempo real — tudo de forma automatizada.

1. Healthcheck simples do GeoServer

O endpoint /about/version retorna informações básicas do servidor. É ideal para um healthcheck inicial:

curl -u admin:geoserver \
http://localhost:8080/geoserver/rest/about/version.json

A resposta inclui versão do GeoServer, build e dados do ambiente. Se este endpoint responder com sucesso (HTTP 200), sabemos que o servidor está no ar.

2. Consultando camadas e stores

Para monitorar se um workspace ou store está ativo, podemos listar camadas ou stores disponíveis. Exemplo para listar todos os stores do workspace cite:

curl -u admin:geoserver \
http://localhost:8080/geoserver/rest/workspaces/cite/datastores.json

A resposta retornará a lista de stores configurados. Um script pode percorrer essa lista para verificar se conexões com PostGIS ou arquivos shapefile estão acessíveis.

3. Consultando Logs do GeoServer

O GeoServer permite acessar os logs via REST API, mas esse recurso não vem habilitado por padrão.

Para ativá-lo, siga os passos:

  1. Acesse a interface web do GeoServer (http://localhost:8080/geoserver).
  2. Vá em Serviços → Logging.
  3. Certifique-se de escolher um perfil de log (por exemplo, DEFAULT_LOGGING ou GEOSERVER_DEVELOPER_LOGGING).
  4. Marque a opção Enable REST access to logs (se disponível na versão do seu GeoServer).
  5. Salve a configuração.

Após habilitar, você poderá consultar os logs via REST:

curl -u admin:geoserver \
http://localhost:8080/geoserver/rest/logs.json

A resposta retorna mensagens recentes do log do servidor, úteis para detectar falhas em publicações de camadas, erros de conexão ou problemas de configuração.

⚠ Atenção à Segurança:

  • Habilitar logs via REST expõe informações sensíveis, como nomes de camadas, queries SQL e conexões com bancos (PostGIS).
  • Esse endpoint deve ser acessível apenas a usuários com **permissão administrativa**. Não deixe disponível para usuários comuns ou público geral.
  • Combine essa configuração com restrições de rede (VPN, firewall ou proxy reverso) e autenticação forte.
  • Evite expor logs completos em ambientes de produção. Prefira usar ferramentas de monitoramento externas (Prometheus, Grafana, ELK) para coleta de logs.

4. Monitoramento em Python

Podemos criar um script em Python para automatizar healthchecks e alertas:

import requests

GEOSERVER_URL = "http://localhost:8080/geoserver/rest"
AUTH = ("admin", "geoserver")

# Healthcheck
r = requests.get(f"{GEOSERVER_URL}/about/version.json", auth=AUTH)
print("Status GeoServer:", r.status_code)

# Listar stores do workspace cite
r = requests.get(f"{GEOSERVER_URL}/workspaces/cite/datastores.json", auth=AUTH)
if r.status_code == 200:
    stores = r.json()
    print("Stores encontrados:", [s["name"] for s in stores["dataStores"]["dataStore"]])

Esse script pode ser integrado a ferramentas de monitoramento como cron jobs, Prometheus ou até sistemas de alerta via Slack/Telegram.

Conclusão

Monitorar o GeoServer via REST API permite detectar problemas rapidamente e automatizar verificações essenciais, reduzindo falhas em produção.

by Fernando Quadro at September 10, 2025 12:00 PM

September 09, 2025

Los Sistemas de Información Geográfica (SIG) se han convertido en una herramienta clave para transformar datos en conocimiento y mejorar la manera en que se gestionan proyectos en todo tipo de sectores. Desde la planificación urbana hasta la gestión de emergencias, los SIG permiten tomar decisiones mejor fundamentadas y estratégicas.

Mañana miércoles 10 de septiembre a las 10:00 a.m. (hora de Panamá) tendrás la oportunidad de participar en un webinar en el que hablaremos de nuestra experiencia práctica sobre cómo los SIG apoyan procesos de gestión y decisión en contextos reales.

👉 ¿Por qué asistir?

  • Conocerás casos de uso reales de SIG en diferentes ámbitos.
  • Descubrirás cómo las herramientas de la Suite gvSIG ayudan a optimizar recursos y anticipar problemas.
  • Obtendrás una visión clara de por qué los SIG son aliados estratégicos en la transformación digital.

📅 Fecha: Miércoles 10 de septiembre, 2025
🕙 Hora: 10:00 a.m.

✅ Regístrate gratis aquí: Formulario de inscripción

by Alvaro at September 09, 2025 03:02 PM

Prezado leitor,

No dia a dia, é comum termos diversos workspaces configurados, cada um com seus stores, layers e estilos associados. Em ambientes de produção, manter cópias de segurança é fundamental para prevenir perdas em caso de falhas ou para replicar configurações em outro servidor.

1. Exportar (backup) um workspace

O GeoServer expõe endpoints REST que permitem exportar a configuração completa de um workspace em formato .zip.

# Exporta o workspace "meu_workspace"
# -u admin:geoserver → autenticação no GeoServer (usuário:senha)
# -XGET → método HTTP utilizado
# -H "Accept: application/zip" → define que a resposta será um arquivo ZIP
# URL do endpoint com ?recurse=true → inclui stores, layers e estilos associados
# -o meu_workspace_backup.zip → salva o backup no arquivo ZIP local

curl -u admin:geoserver -XGET \
  -H "Accept: application/zip" \
  http://localhost:8080/geoserver/rest/workspaces/meu_workspace?recurse=true \
  -o meu_workspace_backup.zip

Como resultado você terá um arquivo meu_workspace_backup.zip contendo toda a estrutura do workspace desejado.

2. Importar (restore) um workspace

Para restaurar, basta enviar o .zip de volta ao GeoServer via POST:

# Restaura o workspace a partir do backup ZIP
# -u admin:geoserver → autenticação no GeoServer
# -XPOST → método HTTP utilizado
# -H "Content-type: application/zip" → indica que o arquivo enviado é ZIP
# --data-binary @meu_workspace_backup.zip → envia o arquivo binário
# URL do endpoint /workspaces → local onde o workspace será recriado

curl -u admin:geoserver -XPOST \
  -H "Content-type: application/zip" \
  --data-binary @meu_workspace_backup.zip \
  http://localhost:8080/geoserver/rest/workspaces

Esse processo recriará o workspace no GeoServer de destino, com toda a configuração previamente exportada.

3. Conclusão

Com poucos comandos, conseguimos automatizar o processo de backup e restore de workspaces via REST API. Essa prática é indispensável para migrações, ambientes de testes e recuperação rápida em caso de falhas.

by Fernando Quadro at September 09, 2025 12:00 PM

September 08, 2025

Comment le jumeau numérique de la Terre et des océans change la donne

Observer, comprendre, agir

La thématique des GeoDataDays 2025 « Agir dans un monde en évolution : indispensables geodata » est ancrée dans un contexte marqué par le changement climatique, l’érosion de la biodiversité, les transformations rapides de nos territoires et les tensions géopolitiques, les décideurs ont besoin d’outils qui dépassent la simple photographie de la situation. Pour agir efficacement, il faut d’abord observer et comprendre les dynamiques en cours. C’est précisément l’ambition du jumeau numérique multi-milieux développé par Geomatys : plus qu’une carte, il s’agit d’une vision vivante et évolutive de la Terre qui intègre en continu données satellites, capteurs, mesures in situ et modèles pour transformer la donnée en outil visuellement parlant.

 

La video ci-contre présente les capabilités du jumeau numérique.

Observer : une infrastructure solide et stratégique

Geomatys a mis en place une architecture complète pour collecter, organiser et visualiser les données. Qu’il s’agisse d’informations géographiques, hydrographiques, océanographiques ou météorologiques (GHOM), la plateforme rend la lecture de ces données accessible en 4D grâce à des capacités avancées de visualisation et de traitements, dans une infrastructure cloud-native.

L’écosystème repose sur le moteur de jeu Unreal Engine 5, ainsi que notre socle logiciel Examind Server, le tout conforme aux standards OGC, garantissant l’interopérabilité et la pérennité de la solution. En résumé, cet outil permet donc disposer d’une base fiable et performante, pour passer au stade de l’analyse.

Comprendre : analyser n’a jamais été aussi simple

Cependant, observer ne suffit pas : il faut donner du sens à la masse de données collectées. Grâce à des algorithmes d’IA ou des modèles de prédiction, ces données sont croisées, fusionnées, traduites en scénarios compréhensibles : montée des eaux, submersions, état écologique, pollution marine… Comprendre signifie transformer des données brutes en informations lisibles et exploitables pour les chercheurs comme pour les décideurs.

 Par exemple, en croisant l’imagerie satellite avec les modèles de courant, on peut visualiser et anticiper la dérive de bancs de déchets en mer ; on peut faire de même avec les traces AIS et le niveau de houle, pour détecter des transbordements clandestins. Ces cas d’usage montrent comment le croisement et la fusion de données transforme l’observation en analyses immédiatement exploitables.

Agir : transformer la connaissance en décision

La dernière étape, c’est l’action. Le jumeau numérique devient un levier pour planifier, anticiper et décider. Dans un contexte de crises et d’exigences de durabilité, les collectivités, agences et acteurs institutionnels trouvent dans cette plateforme un environnement immersif pour simuler et planifier. L’intégration de flux en temps réel, la représentation de scénarios tactiques et la possibilité de déployer des IHM directement sur le terrain permettent d’agir sans délai, au plus près des besoins. Un responsable militaire, par exemple, peut intégrer en temps-réel les effets de la météo dans la simulation d’un théâtre d’opérations. Agir, c’est utiliser la connaissance acquise pour guider des choix concrets et coordonnés, partout où les décisions doivent être prises.

Conclusion — Observer, comprendre, agir

Avec le jumeau numérique Terre & Océans, Geomatys ne se limite pas à représenter la planète : l’objectif est de la comprendre, pour mieux agir. Dans un monde où chaque décision doit intégrer des données fiables et des perspectives d’avenir, cet outil offre une approche souveraine, interopérable et immersive. Les données deviennent alors des leviers concrets pour prendre les bonnes décisions et anticiper les défis.

The post Comment notre jumeau numérique de la Terre & Océans change la donne first appeared on Geomatys.

by Jordan Serviere at September 08, 2025 12:35 PM

September 07, 2025

¿Alguna vez has querido preguntarle a tu aplicación qué datos tiene o qué puede hacer con ellos, usando tus propias palabras? Esa fue la pregunta que me hice a principios de este año cuando empecé a ver que los modelos de lenguaje (LLMs, Large Language Models o Modelos de Lenguaje Grande) podían hacer cosas increíbles… pero siempre desde un navegador web, lejos de la aplicación de escritorio.

Como muchos sabéis, llevo años trabajando en gvSIG Desktop, una aplicación Java de escritorio con mucha historia y mucho código. La idea de integrar capacidades de IA directamente en la aplicación me pareció fascinante, pero tenía un problema: todo lo que veía requería frameworks complejos de Python o soluciones en la nube que no encajaban con nuestra realidad, requerian versiones modernas de java o python con las que no podia contar.

Así que me dije “voy a intentar hacerlo a mi manera”. Voy a contaros cómo, en unos dias, conseguí que gvSIG desktop empezara a conversar con Gemini usando poco más que las librerías HTTP de Java y Jython.

El primer paso, un chat simple pero funcional

Lo primero que necesitaba era lo más básico, una ventana de chat dentro de gvSIG desktop que pudiera enviar mensajes a la API de Gemini y mostrar las respuestas.

Para mantener las cosas simples, usé el entorno de scripting y Jython para prototipar rápidamente la interfaz de usuario, y para la comunicación con la API, me bastó con las librerías HTTP de Java.

El núcleo de la comunicación se reducía a esto: construir el payload JSON correcto y enviarlo.

from java.net import URL, HttpURLConnection
from java.io import BufferedReader, InputStreamReader, OutputStreamWriter
from javax.json import Json

class GeminiClient:
    def __init__(self):
        self.history = []
        self.api_key = "tu_api_key"
        self.api_url = "https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent"

    def send_message(self, user_prompt):
        # Construir la solicitud HTTP
        url = URL(self.api_url + "?key=" + self.api_key)
        conn = url.openConnection()
        conn.setRequestMethod("POST")
        conn.setRequestProperty("Content-Type", "application/json")
        conn.setDoOutput(True)

        # Construir el payload JSON
        payload = {
            "contents": [{
                "parts": [{"text": user_prompt}]
            }]
        }

        # Enviar la solicitud
        output_stream = conn.getOutputStream()
        writer = OutputStreamWriter(output_stream, "UTF-8")
        writer.write(Json.createObjectBuilder(payload).build().toString())
        writer.flush()

        # Leer la respuesta
        reader = BufferedReader(InputStreamReader(conn.getInputStream()))
        response = ""
        line = reader.readLine()
        while line is not None:
            response += line
            line = reader.readLine()

        return response

La magia estaba en construir el Json correcto que espera la API de Gemini. Pero una vez resuelto esto, en pocas horas ya tenía una ventana de chat funcionando dentro de gvSIG.

Primer prototipo funcionando
El primer prototipo era sencillo, pero funcionaba. Podía escribir preguntas y obtener respuestas.

El desafío real, más allá del chat conversacional

Un chat conversacional está bien para hacer pruebas, pero no es muy útil en una aplicación de escritorio. El verdadero reto era cómo usar el LLM para algo práctico. En nuestro caso, se me ocurrió que podría ayudar con la ficha de búsqueda de gvSIG, que aunque es potente, puede resultar compleja para los usuarios.

Pero aquí aparecía otro problema ¿cómo le pido al LLM que trabaje con mis datos sin enviarle información sensible, sin enviarle los datos de las capas que tengo cargadas la la aplicación? La solución fue enseñarle a entender la estructura de mis datos, no darle los datos en sí.

El arte del prompting estructurado, enseñándole las reglas del juego

La verdadera magia no estaba en la conexión HTTP o en la cacharreria Json que habia que hacer para hablar con el LLM, sino en el diseño del system prompt que conseguiría que el LLM entendiera exactamente cómo tenía que comportarse, estaba programando con palabras. El prompt se convirtió en el cerebro del sistema, las reglas del juego que transformaban un modelo de lenguaje genérico en un especialista de gvSIG desktop.

El desafío era triple:

  1. Contexto: Darle al LLM información suficiente sobre la estructura de los datos
  2. Comportamiento: Definir exactamente cómo debía responder para cada tipo de consulta
  3. Formato: Forzar una salida estructurada y parseable

El prompt base tenía que establecer las reglas fundamentales.

La estructura del esqueleto principal del prompt que construí fue algo parecido a esto:


BASE_PROMPT = u"""
Eres un asistente especializado en gvSIG Desktop. 
Responde EXCLUSIVAMENTE en castellano con objetos JSON válidos.

TIPOS DE CONSULTA SOPORTADOS:
- "text": Para consultas generales
- "sql": Para consultas SQL sobre las tablas
- "plantuml": Para diagramas de entidad-relación

REGLAS ESTRICTAS PARA SQL:
- ⛔ Nunca incluyas esquemas en las consultas
- ✅ Usa solo SQL-92 estándar  
- 🌍 Solo funciones espaciales de SQL/MM y OGC SFS
- 🚫 Evita sintaxis no estándar
- 📏 Limita a 1000 resultados

ESTRUCTURA DE RESPUESTA OBLIGATORIA:
{
  "type": "tipo_de_respuesta",
  // campos adicionales según el tipo
}

EJEMPLO SQL:
{
  "type": "sql",
  "sql": "SELECT * FROM tabla WHERE condición LIMIT 1000;",
  "title": "Descripción clara",
  "esValorEscalar": false
}

EJEMPLO PLANTUML:
{
  "type": "plantuml", 
  "diagram": "@startuml\\nentity Tabla\\n@enduml",
  "title": "Diagrama de entidades"
}
"""

Con estas reglas, el LLM ya no solo conversaba, sino que generaba instrucciones. La aplicación actuaba como un intérprete: recibía un JSON, miraba el campo “type” y sabía exactamente qué hacer. Si recibía {“type”: “sql”, …}, sabía que debía mostrar un botón que, al pulsarlo, ejecutaría la consulta SQL. Si recibía {“type”: “plantuml”, …}, generaría un botón para visualizar el diagrama.

Los resultados, cuando todo empezó a encajar

La primera vez que probé el sistema completo me resulto impactante. El LLM dejó de ser un simple chatbot para convertirse en un motor de análisis que respondía a mis preguntas con acciones concretas. Una conversación natural se traducía en operaciones reales dentro de gvSIG:

Generación de un diagrama Entidad-Relación a partir de una petición en lenguaje natural

En esta captura se ve cómo el usuario pregunta “Puedes generarme un modelo entidad relación con las tablas a las que tienes acceso?” y el sistema responde con un botón que al hacer clic muestra el diagrama solicitado.

Visualización de los resultados de una consulta SQL en una tabla dentro de gvSIGAquí vemos cómo la orden de “Muestrame las placas que tienen un soporte de acero” el sistema genera una consulta SQL y responde con un botón que al hacer clic muestra el resultado en una tabla.

Creación de un gráfico de barras a través de una conversación con el asistente de IA
Finalmente, una solicitud más compleja como un gráfico de barras se traduce en la visualización de este en la aplicación.

Cada respuesta del sistema correspondía a un Json estructurado que el LLM generaba y que la aplicación parseaba y ejecutaba, mostrando los resultados en tablas o gráficos según el caso.

Detalles de implementación para desarrolladores

La comunicación con la API de Gemini

Implementé un cliente Gemini en Jython que maneja el historial de conversación.

def send_message(self, user_prompt, initial_prompt=None):
    # Añadir mensajes al historial
    if not self.history and initial_prompt is not None:
        self.history.append({"role": "user", "parts": [{"text": initial_prompt}]})

    self.history.append({"role": "user", "parts": [{"text": user_prompt}]})

    # Construir y enviar payload
    payload = self._build_payload()
    response = self._send_request(payload)

    # Procesar respuesta
    generated_text = self._parse_response(response)
    self.history.append({"role": "model", "parts": [{"text": generated_text}]})

    return generated_text

Procesamiento de respuestas Json

Una de las partes más críticas fue el parseo de las respuestas Json del LLM. Muchas veces el LLM mezclaba la respuesta estructurada junto con comentarios, preguntas o peticiones de aclaraciones o información, y habia que separar la respuesta extructurada, el Json, del resto de la conversación.

def extraer_json_de_markdown(texto_completo):
    marca_inicio = u'```json'
    marca_fin = u'```'

    pos_inicio = texto_completo.find(marca_inicio)
    if pos_inicio != -1:
        pos_contenido_inicio = pos_inicio + len(marca_inicio)
        pos_fin = texto_completo.find(marca_fin, pos_contenido_inicio)

        if pos_fin != -1:
            json_encontrado = texto_completo[pos_contenido_inicio:pos_fin].strip()
            return json_encontrado, texto_completo[:pos_inicio] + texto_completo[pos_fin + len(marca_fin):]

    return None, texto_completo

Reflexiones… y una pregunta incómoda

Este primer prototipo me demostró varias cosas importantes:

  1. No necesitas frameworks complejos para empezar a integrar IA en aplicaciones legacy.
  2. El prompting estructurado es la clave: Puedes “programar” el comportamiento de un LLM con instrucciones precisas.
  3. Java/Jython y las librerías estándar son suficientes para comunicarse con APIs modernas.

Tenía una prueba de concepto que funcionaba. Pero mientras veía las respuestas de la IA aparecer en la pantalla, una pregunta empezó a rondarme la cabeza, una que podia convertir este experimento en un simple juguete personal.

Cada una de esas respuestas “mágicas” requería una llamada a una API de pago. ¿Cómo iba a compartir esto con alguien sin que ni ellos ni yo nos arruinásemos en el intento? ¿Pedirle a los usuarios que consiguieran su propia API Key solo para probar mi herramienta? No parecia realista.

De repente, el mayor desafío ya no era técnico, sino de distribución. Pero antes de poder resolver ese problema, necesitaba que la herramienta fuera tan útil, tan indispensable, que mereciera la pena luchar por ella. Tenía que dejar de ser un chat para convertirse en un verdadero asistente que entendiera el contexto de lo que el usuario estaba haciendo en gvSIG desktop.

De eso, y de cómo el contexto lo cambió todo, hablaré en el siguiente artículo.

Un saludo.

by Joaquin del Cerro at September 07, 2025 10:06 PM

September 06, 2025

My word, (and forgive the language), but what an arse of a job they’ve made of this. This is at the Brussels terminal of the Eurostar where they’ve superimposed some historical mapping, geology maps, the tube map and a picture of Shakespeare and some other random graphics to make a horror of a montage for the toilet doors.

The tube stations for Steven’s beloved football team has been partially obscured by the lock on the door.

That might just be an unfortunate coincidence, but I’ve not seen such a need for Positional Accuracy Improvement (“PAI”) on anything of this scale since the late ’90’s.

But its not just the layout. The whole thing is littered with errors. The King might indeed be quite Cross that they’ve not named a major London station correctly. Yes, that really does say St Francis!

Whilst the quality of the original image isn’t great, if you can zoom in to it you’ll see a whole host of other errors, leaving you with a bit of Mappery birthday fun trying to spot them.

If anybody is passing through Brussels and can get a better quality image that would be great. In the meantime have fun! The station one stop west of Bank is interesting … as is the stop east of Monument … but there are many more!

by Dan at September 06, 2025 11:01 AM

Today is our 7th birthday, really quite amazing. That’s 2,000 posts and 3,000 images!

I chose these pix from the Shipping House in Amsterdam (aka Scheepvaarthuis) that Reinder sent to me for 2 reasons – firstly, because the windows are absolutely beautiful and represent the essence of a Map in the Wild and secondly because Reinder has been one of our greatest supporters in the last 7 years of Mappery, so thanks to Reinder.

Also thanks on this special day to Ken who helped start the site, to Arnaud who keeps it running and contributes loads of posts and to Dan. There would be no Mappery without you.

And a massive thank you to all of you who follow us, send us Maps in the Wild and give us feedback.

by Steven at September 06, 2025 09:00 AM

September 05, 2025

Prezado leitor,

Neste tutorial você vai aprender, passo a passo, como enviar um shapefile diretamente para o GeoServer usando a REST API. A diferença aqui é que, em vez de o arquivo ser salvo na pasta data_dir, ele será importado automaticamente para o PostGIS, utilizando o plugin Importer do GeoServer.

Esse fluxo é extremamente útil para automatizar processos de ingestão de dados em ambientes de produção, evitando a manipulação manual da pasta data_dir.

Além disso, com a REST API, você pode integrar esse processo em scripts Python, pipelines de ETL ou até em rotinas de integração contínua (CI/CD).

Vamos ao passo a passo:

1. Criação do Store

Antes de importar o shapefile, precisamos garantir que existe um store configurado apontando para o banco PostGIS.

Isso pode ser feito pela própria REST API, com o seguinte comando:

curl  -u admin:geoserver -XPOST -H "Content-type: application/json" -d @postgis.json "http://localhost:8080/geoserver/rest/workspaces/cite/datastores.json"

O comando acima cria um novo Store no GeoServer, e as configurações ficam no arquivo postgis.json, quem contem as informações de conexão da base de dados que você deseja utilizar no GeoServer, conforme o exemplo a abaixo:

{
  "dataStore": {
    "name": "postgis",
    "type": "PostGIS",
    "workspace": {
      "name": "cite"
    },
    "connectionParameters": {
      "entry": [
        {"@key": "schema","$": "public"},
        {"@key": "database","$": "postgres"},
        {"@key": "host","$": "localhost"},
        {"@key": "port","$": "5432"},
        {"@key": "passwd","$": "postgres"},
        {"@key": "dbtype","$": "postgis"},
        {"@key": "user","$": "postgres"},
        {"@key": "Estimated extends","$": "true"},
        {"@key": "encode functions","$": "true"},
        {"@key": "Loose bbox","$": "true"},
        {"@key": "Method used to simplify geometries","$": "PRESERVETOPOLOGY"},
        {"@key": "Support on the fly geometry simplification","$": "true"},
        {"@key": "validate connections","$": "true"},
        {"@key": "Connection timeout","$": "20"},
        {"@key": "min connections","$": "1"},
        {"@key": "max connections","$": "10"},
        {"@key": "Evictor tests per run","$": "3"},
        {"@key": "Test while idle","$": "true"},
        {"@key": "Max connection idle time","$": "300"}
      ]
    },
    "_default": true
  }
}

2. Definição para importação

É importante ressaltar que para executar o comando abaixo, é necessário que o plugin Importer esteja instalado no seu GeoServer, pois é ele que fará a importação do shapefile para o banco de dados. O primeiro passo é preparar a tarefa através do seguinte comando:

curl.exe -u admin:geoserver -XPOST -H "Content-type: application/json" -d @import.json "http://localhost:8080/geoserver/rest/imports"

O arquivo import.json deve conter as informações de onde você deseja armazenar o arquivo shapefile, no caso workspace e store:

{
   "import": {
      "targetWorkspace": {
         "workspace": {
            "name": "cite"
         }
      },
      "targetStore": {
         "dataStore": {
            "name": "postgis"
         }
      }
   }
}

O comando acima irá retornar um ID (no nosso exemplo é o 0), que você irá inserir no link de resposta ao GeoServer. Após a execução do comando acima temos uma importação vazia, sem tarefas. Para adicionar uma tarefa, publique o shapefile na lista de tarefas:

curl.exe -u admin:geoserver -F name=biomas_srv.zip -F filedata=@biomas_srv.zip "http://localhost:8080/geoserver/rest/imports/0/tasks"

3. Apontar para o Store

Como enviamos um shapefile, o importador assume que o destino será um repositório de shapefiles. Para importar para o PostGIS, precisaremos redefini-lo, e faremos isso através do arquivo target.json:

{
  "dataStore": {
    "name":"postgis"
  }
}

Coloque esse arquivo na requisição abaixo:

curl.exe -u admin:geoserver -XPUT -H "Content-type: application/json" -d @target.json "http://localhost:8080/geoserver/rest/imports/0/tasks/0/target"

4. Realizar a importação

Por fim, executamos a importação enviando um POST da seguinte forma:

curl.exe -u admin:geoserver -XPOST "http://localhost:8080/geoserver/rest/imports/0"

Se tudo correr bem, o shapefile será carregado diretamente no seu banco PostGIS e publicado no GeoServer.

5. BÔNUS

Para quem deseja automatizar o processo, segue um exemplo de um Script Python usando a biblioteca requests. Veja como usar:

1. Salve o script em um arquivo, por exemplo import_shapefile.py.
2. Certifique-se de instalar a biblioteca necessária:

pip install requests

3. Ajuste os parâmetros de conexão (usuário, senha, banco, shapefile, workspace etc.) conforme seu ambiente.
4. Agora execute o script: python import_shapefile.py

# Script import_shapefile.py

import requests
import json

# Configurações
GEOSERVER_URL = "http://localhost:8080/geoserver/rest"
AUTH = ("admin", "geoserver")  # usuário e senha
WORKSPACE = "cite"
DATASTORE = "postgis"
SHAPEFILE = "biomas_srv.zip"

# 1. Criar o DataStore (caso ainda não exista)
postgis_json = {
    "dataStore": {
        "name": DATASTORE,
        "type": "PostGIS",
        "workspace": {"name": WORKSPACE},
        "connectionParameters": {
            "entry": [
                {"@key": "schema", "$": "public"},
                {"@key": "database", "$": "postgres"},
                {"@key": "host", "$": "localhost"},
                {"@key": "port", "$": "5432"},
                {"@key": "passwd", "$": "postgres"},
                {"@key": "dbtype", "$": "postgis"},
                {"@key": "user", "$": "postgres"}
            ]
        }
    }
}

resp = requests.post(
    f"{GEOSERVER_URL}/workspaces/{WORKSPACE}/datastores",
    auth=AUTH,
    headers={"Content-type": "application/json"},
    data=json.dumps(postgis_json)
)

print("Criação do DataStore:", resp.status_code)

# 2. Criar importação
import_json = {
    "import": {
        "targetWorkspace": {"workspace": {"name": WORKSPACE}},
        "targetStore": {"dataStore": {"name": DATASTORE}}
    }
}

resp = requests.post(
    f"{GEOSERVER_URL}/imports",
    auth=AUTH,
    headers={"Content-type": "application/json"},
    data=json.dumps(import_json)
)

import_id = resp.json()["import"]["id"]
print("ID da importação:", import_id)

# 3. Adicionar o shapefile à importação
with open(SHAPEFILE, "rb") as f:
    resp = requests.post(
        f"{GEOSERVER_URL}/imports/{import_id}/tasks",
        auth=AUTH,
        files={"filedata": f},
        data={"name": SHAPEFILE}
    )

print("Upload shapefile:", resp.status_code)

# 4. Ajustar destino para PostGIS
target_json = {"dataStore": {"name": DATASTORE}}

resp = requests.put(
    f"{GEOSERVER_URL}/imports/{import_id}/tasks/0/target",
    auth=AUTH,
    headers={"Content-type": "application/json"},
    data=json.dumps(target_json)
)

print("Redefinição destino:", resp.status_code)

# 5. Executar importação
resp = requests.post(
    f"{GEOSERVER_URL}/imports/{import_id}",
    auth=AUTH
)

print("Execução da importação:", resp.status_code)

by Fernando Quadro at September 05, 2025 07:15 PM

Carol Ely spotted this, “While maps are often used on TV news shows, it took a while for the penny to drop that the entire background and graphic scheme of the MSNBC (US) show Inside with Jen Psaki is a stylized map of Washington DC. It often looks like a Mondrian grid!  I’m a huge fan of maps and Mappery…”

Thanks to Carol for a great spot and for her kind words about Mappery.

Postscript: Carol sent another message “I noticed last night that MSNBC changed the show’s name to “The Briefing with Jen Psaki”. Same graphics” Maybe Jen is no longer on the inside?

by Steven at September 05, 2025 09:00 AM

September 04, 2025

September 03, 2025

Este tutorial mostra como configurar um script que atualiza automaticamente as camadas do GeoServer no GeoNode, utilizando um checksum para detectar alterações.

1. Instalar o checksumdir dentro do container do GeoServer

1.1 Entrar no container do GeoServer

docker exec -it geoserver4my_geonode bash

1.2 Instalar o checksumdir

pip install checksumdir

2. Gerar o checksum (código único) da pasta do GeoServer

O comando checksumdir cria um hash único com base no conteúdo de todos os arquivos da pasta especificada. Isso significa que qualquer alteração em uma camada, SLD ou arquivo dentro do workspace do GeoNode fará o checksum mudar, permitindo que o script detecte automaticamente essas modificações e atualize as camadas no GeoNode.

2.1 Executar o comando:

checksumdir /geoserver_data/data/workspaces/geonode

Anote o código gerado, pois ele será usado na etapa seguinte.

3. Criar um arquivo para armazenar o checksum

3.1 Criar o arquivo:

sudo mkdir /opt/updatelayers
sudo chown geocursos /opt/updatelayers
sudo chgrp www-data /opt/updatelayers
cd /opt/updatelayers
touch layers_updated_md5

3.2 Inserir o código do checksum

nano layers_updated_md5

Cole o checksum gerado na etapa anterior e salve o arquivo.

4. Criar o script de execução automática

4.1 Criar o arquivo do script:

touch cron_updatelayers.sh

4.2 Adicionar o código no script:

geoserver="geoserver4my_geonode"
geonode="django4my_geonode"

md5=$(docker exec -i $geoserver checksumdir /geoserver_data/data/workspaces/geonode)

if [[ $md5 != $(cat /opt/updatelayers/layers_updated_md5) ]]; then
    echo "Atualizando camadas"
    echo $md5 > /opt/updatelayers/layers_updated_md5
    docker exec -i $geonode python3 manage.py updatelayers
fi

4.3 Agora você precisa tornar o arquivo executável:

chmod +x /opt/updatelayers/cron_updatelayers.sh

5. Configurar o cron para execução automática

5.1 Abrir o arquivo crontab:

sudo nano /etc/crontab

5.2 Adicionar a linha para executar o script a cada 5 minutos

Lembre-se de alterar o caminho do script conforme a sua configuração:

*/5 * * * * geocursos bash /opt/updatelayers/cron_updatelayers.sh

Pronto! Agora seu GeoServer irá verificar periodicamente alterações nas camadas e atualizar automaticamente no GeoNode quando houver mudanças.

Se você quiser conferir se o comando está sendo executando, basta executar:

sudo grep CRON /var/log/syslog

Por último, mas não menos importante, gostaria de agradecer ao Diego Varela por disponibilizar esse script.

by Fernando Quadro at September 03, 2025 09:57 PM

September 02, 2025

Prezado leitor,

Se você está implantando o GeoNode na sua infraestrutura e deseja conectar um banco de dados já existente, este tutorial irá guiá-lo passo a passo para realizar a configuração corretamente.

1. Descobrir o endereço IP da Rede Docker

Para identificar a rede que está rodando o seu GeoNode, execute:

/opt/geonode_custom/my_geonode> docker network inspect my_geonode_default | grep Subnet

2. Descobrir o IP da máquina Linux

Para descobrir o endereço IP da máquina onde o Docker está rodando:

/opt/geonode_custom/my_geonode> ifconfig

3. Certificar que os containers Docker estejam inativos

docker-compose down

4. Desabilitar o banco de dados interno do GeoNode

Edite o arquivo docker-compose.yml e comente as linhas referentes ao PostGIS interno, para evitar conflitos com o banco externo:

# PostGIS database.
  #db:
  #  image: ${COMPOSE_PROJECT_NAME}/postgis:${POSTGRES_BASE_IMAGE_VERSION}
  #  build:
  #    context: ./docker/postgresql
  #    dockerfile: Dockerfile
  #    args:
  #      - BASE_IMAGE_VERSION=${POSTGRES_BASE_IMAGE_VERSION}
  #  command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}"
  #  container_name: db4${COMPOSE_PROJECT_NAME}
  #  env_file:
  #    - .env
  #  volumes:
  #    - dbdata:/var/lib/postgresql/data
  #    - dbbackups:/pg_backups
  #  restart: unless-stopped
  #  healthcheck:
  #    test: "pg_isready -d postgres -U postgres"
  # uncomment to enable remote connections to postgres
  #ports:
  #  - "5432:5432"

  # dbdata:
  #    name: ${COMPOSE_PROJECT_NAME}-dbdata
  #  dbbackups:
  #    name: ${COMPOSE_PROJECT_NAME}-dbbackups

Você precisa desabilitar a dependência do Django ao banco para que não dê erro ao tentar subir o container novamente:

django:
#  depends_on:
#   - db

E também a dependência do GeoServer e Celery ao Django:

#  depends_on:
#   - django:
#      condition: service_healthy

5. Parâmetros necessários no banco de dados externo

Quanto ao banco de dados externo, espera-se que ele tenha os seguintes parâmetros:

  • Usuário com senha para conexão
  • Base de dados para as tabelas Django do GeoNode
  • Base de dados para os dados espaciais
  • Endereço IP do servidor de banco externo
  • Porta de acesso ao banco
  • Endereço IP da rede Docker

6. Preparar o banco de dados externo

O GeoNode precisa de duas bases de dados: uma para o Django (geonode) e outra para os dados espaciais (geonode_data). Veja:

-- Criar usuário com senha forte
CREATE USER geonode_user WITH PASSWORD 'geonode123';

-- Criar os bancos com ownership do usuário

CREATE DATABASE geonode OWNER geonode_user;
CREATE DATABASE geonode_data OWNER geonode_user;

-- ==============================
-- Configuração no banco geonode
-- ==============================
-- Abra o banco geonode e execute:

CREATE EXTENSION IF NOT EXISTS postgis;

GRANT ALL ON geometry_columns TO PUBLIC;
GRANT ALL ON spatial_ref_sys TO PUBLIC;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO geonode_user;

-- ==============================
-- Configuração no banco geonode_data
-- ==============================
-- Abra o banco geonode_data e execute:

CREATE EXTENSION IF NOT EXISTS postgis;

GRANT ALL ON geometry_columns TO PUBLIC;
GRANT ALL ON spatial_ref_sys TO PUBLIC;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO geonode_user;

7. Atualizar o arquivo .env com os dados do banco externo

Lembre-se de alterar o número do IP e a porta de acordo com a sua realidade (onde seu banco de dados está instalado), no meu caso o IP do meu banco é o 192.168.0.245.

# -------------------------------
# Backend
# -------------------------------
GEONODE_DATABASE=geonode
GEONODE_DATABASE_USER=geonode_user
GEONODE_DATABASE_PASSWORD=geonode123
GEONODE_GEODATABASE=geonode_data
GEONODE_GEODATABASE_USER=geonode_user
GEONODE_GEODATABASE_PASSWORD=geonode123
GEONODE_DATABASE_SCHEMA=public
GEONODE_GEODATABASE_SCHEMA=public
DATABASE_HOST=192.168.0.245
DATABASE_PORT=5432
DATABASE_URL=postgis://geonode_user:geonode123@192.168.0.245:5432/geonode
GEODATABASE_URL=postgis://geonode_user:geonode123@192.168.0.245:5432/geonode_data

8. Alterar o arquivo pg_hba.conf

Agora é necessário inserir no arquivo do PostgreSQL as permissões de acesso a máquina e a rede onde está rodando o docker, da seguinte forma:

# -------------------------------
# GeoNode connections
# -------------------------------

# Permite que a rede dos containers Docker do GeoNode acesse o PostgreSQL
host   geonode        geonode_user   172.18.0.0/16        md5
host   geonode_data   geonode_user   172.18.0.0/16        md5

# Permite que a VM Linux (192.168.186.137) e qualquer host da sub-rede 192.168.0.0/24 acessem o PostgreSQL
host   geonode        geonode_user   192.168.186.137/32   md5
host   geonode_data   geonode_user   192.168.186.137/32   md5
host   geonode        geonode_user   192.168.0.0/24       md5
host   geonode_data   geonode_user   192.168.0.0/24       md5

Observações:

  • 172.18.0.0/16 → rede Docker
  • 192.168.186.137/32 → IP da VM Linux

Após alterado o arquivo, você deve reiniciar o serviço do PostgreSQL. Se for no Linux, faça da seguinte forma:

sudo service postgresql restart

9. Reiniciar o docker

Para finalizar o processo, faça um novo build e depois suba o docker:

/opt/geonode_custom/my_geonode> docker-compose build 
/opt/geonode_custom/my_geonode> docker-compose up -d

Agora é só testar e ver se funcionou.

10. Ambiente

Para esse teste eu utilizei:

– Máquina com Windows 11 e PostgreSQL 16 (IP 192.168.0.245)
– Ubuntu 22.04 rodando no VMWare, dentro da máquina Windows (IP 192.168.186.137)

by Fernando Quadro at September 02, 2025 06:52 PM

It's T-24 days to the Bear 100. I've been busy with life, training, and work. Blogging has suffered. I'm going to catch up a bit this week.

Week 28 was a solid training week. I'm very pleased with the work I did.

  • 52.3 miles running

  • 12,943 feet D+ running

  • 17 hours, 40 minutes all training

I did five runs, all with significant elevation gains, and all over 90 minutes. I also did one yoga session, one session of tempo intervals on my favorite elliptical/stair-stepper hybrid at its max vert setting, and a lot of short bike rides.

I found a way to extend one of my favorite local segments to make one mile up-and-down laps with 250 feet of positive elevation gain (dénivelé positif, in French, or "D+") . This is slightly steeper than the Bear's rate of 230 feet per mile. Friday I did four laps. This week I'll do the same workout and at least five laps. It's not the most scenic run, but it's close to home and doesn't require a 20-minute drive. A trail-running podcast episode about crewing and pacing made the repeats pass quickly.

https://live.staticflickr.com/65535/54759996263_62aa0c4de9_c.jpg

Spiky, vibrant green moss with some darker green leafy bits.

Sunday I went out for six hours in conditions that I expect at the Bear and at a similar elevation, on a route with a 3,000 foot climb and a 2,400 foot climb. I counted my carbs, fluids, and salt intake to use in planning my race fueling and hydration. I ran nine miles up and over Crosier Mountain (9,250 feet, or 2,819 meters) and down to the Glen Haven General Store for water, potato chips, peanut M&Ms, and a Coke. Then I reversed course, summitted again, and then ran back down to my car. Nine miles is a typical gap between aid stations at the Bear. It was a useful simulation. My legs felt good, my gear was fine, my fueling and hydration adequate.

The second half of August has been pretty wet and the mountain vegetation is unusually lush. I saw thriving moss and ferns on the shady slopes of the Big Thompson canyon, and running water in the springs higher up. The trail conditions were fabulous, neither muddy nor dusty.

https://live.staticflickr.com/65535/54760107550_b28bc5cf02_b.jpg

A sloping grassy meadow with pine trees and high mountains in the background under a partly cloudy sky.

by Sean Gillies at September 02, 2025 12:51 AM

The PostGIS Team is pleased to release PostGIS 3.6.0! Best Served with PostgreSQL 18 Beta3 and recently released GEOS 3.14.0.

This version requires PostgreSQL 12 - 18beta3, GEOS 3.8 or higher, and Proj 6.1+. To take advantage of all features, GEOS 3.14+ is needed. To take advantage of all SFCGAL features, SFCGAL 2.2.0+ is needed.

3.6.0

This release includes bug fixes since PostGIS 3.5.3 and new features.

by Regina Obe at September 02, 2025 12:00 AM

September 01, 2025

GeoServer 2.26.4 release is now available with downloads (bin, war, windows), along with docs and extensions.

This is a maintenance (now archive) release of GeoServer, providing existing installations with minor updates and bug fixes. GeoServer 2.26.4 is made in conjunction with GeoTools 32.4, and GeoWebCache 1.26.4. Please note that this is the final scheduled release in the 2.26.x series - it is time to upgrade to a supported version.

Thanks to Peter Smythe (AfriGIS) for making this release, and to Jody for testing it.

Security Considerations

This release addresses security vulnerabilities and is considered an important update for existing installations.

The use of the CVE system allows the GeoServer team to reach a wider audience than blog posts. See project security policy for more information on how security vulnerabilities are managed.

Upgrade instructions

Please take note of the Upgrade Instructions, specifically:

  • The global setting Unrestricted XML External Entity Resolution has been replaced with the ENTITY_RESOLUTION_UNRESTRICTED application property.

    This change primarily affects application schema users that have not yet adopted ENTITY_RESOLUTION_ALLOWLIST. See update instructions for details.

  • Due to a user interface change, it is no longer necessary to generate a masterpw.info when upgrading an older data directory.

    If this file is present from an earlier upgrade, it is still considered a security warning and is noted on the welcome page.

Release notes

New Feature:

  • GEOS-11805 Option to disable the management of stored queries
  • GEOS-11911 Application property ROOT_LOGIN_ENABLED

Improvement:

  • GEOS-11867 Improve entity resolution
  • GEOS-11877 Improve CoverageView composition to support noData fill on missing bands/coverages
  • GEOS-11892 Column mentioning user that performed last modification for layers and stores list UI

Bug:

  • GEOS-10728 Cannot download GeoPackage if the source data contains UUID types
  • GEOS-11820 WCS spatial sub-setting does not work when native CRS != declared CRS
  • GEOS-11832 count=0 service exception for some formats
  • GEOS-11866 Prevent requests setting variables that should only be set by GeoServer
  • GEOS-11896 WPS map download flips east/west coordinates
  • GEOS-11900 CRS:XY syntax builds isolated CRSs that do not leverage the EPSG database transformation library

Task:

  • GEOS-11831 OseoDispatcherCallback improvements
  • GEOS-11852 Remove master password info page
  • GEOS-11853 Clarify keystore vs master vs root password
  • GEOS-11854 Generation of security/masterpw.info no longer required
  • GEOS-11869 Replace entity resolution setting with application property

For the complete list see 2.26.4 release notes.

Community Updates

Community module development:

  • GEOS-11829 Features templating ability to override schema
  • GEOS-11830 Smart data loader create store page fails when environment variables are in use
  • GEOS-11839 New Community Module for WPS Download in NetCDF output format for spatiotemporal coverages
  • GEOS-11847 Next link is missing in “Search” OGC API - Features proposal implementation when startIndex is not set
  • GEOS-11871 Allow native execution of group by in DGGS store, when grouping on geometries
  • GEOS-11876 WPS Vertical Longitudinal Profile: Support automatic distance computation
  • GEOS-11878 WFS HITS request returns the whole data records on a GML feature templated layer
  • GEOS-11880 OGC API Maps is not showing up in GeoServer home page

Community modules are shared as source code to encourage collaboration. If a topic being explored is of interest to you, please contact the module developer to offer assistance.

About GeoServer 2.26 Series

Additional information on GeoServer 2.26 series:

Release notes: ( 2.26.4 | 2.26.3 | 2.26.2 | 2.26.1 | 2.26.0 | 2.26-M0 )

by Peter Smythe at September 01, 2025 12:00 AM

August 31, 2025

It was great to be able to attend a couple of days of the RGS-IBG Annual International Conference at the University of Birmingham last week. The RGS conference is an annual gathering of around 2000 geographers, with presentations covering the full range of geography - from AI, GIS analysis, quantitative methods, transport geography, animal research, development studies, inclusive research practice, and many many others.

I attended a number of sessions sponsored by the GIScience Research Group and the Quantitative Methods Research Group.

The first one of these was focused on post-graduate researchers (PGRs), with 5 PGRs presenting their research. It was fascinating to hear about the range of topics they were working on, including machine learning based classification of social media data, exploring street crime using crowd sourced street view imagery, and the relationship between housing development and public transportation provision in the UK. The session wrapped up with discussions on the impacts of spatial structure of cities on potential spread of infectious diseases, and a great example from Germany looking at measuring urban growth.

The QMRG (Quantitative Methods Research Group) held their first annual lecture, in conjunction with The Geographical Journal. One of the main aims of this lecture series is to engage more with the theoretical aspects of the issues we face. Quantitative Methods, and GIS more generally, can often be quite data and stats heavy, but we need to remember how this fits into the wider setting of geography.

The first lecture was Mapping Uneven Ambience by Caitlin Robinson, who took us on a fascinating journey through her most recent project looking at the ambient environment.

This was the first stage of a larger project, and was focused on a range of factors around peoples lived experience, including air quality, noise and housing infrastructure. Currently she has explored this through a number of different data sets, including EPC (Energy Performance Certificates) providing information on heating in the home and ventilation, external air quality data from DEFRA and IMD data.

One key dataset that was missing was data on indoor air quality - which is vitally important for this type of work, as it is estimated that in the global north, people spend 80-90% of their time indoors. One of the questions at the end of the presentation provided a potentially useful data source for this, which is often the case at conferences!

The next stage will start looking at the interrelations between the different factors - for example indoor air quality and heating type - which will certainly be interesting to see as the vulnerabilities are often cumulative - exposure to indoor air pollution, combined with poor heating in the winter, will most likely lead to a much poorer outcome than either issue alone.

On the Thursday morning, I attended two sessions on Artificial Intelligence in GIScience and Quantitative Geography, where there were a fascinating range of presentations, looking at the space embedded in census data, embedding geography into vision language models and a wide range of other papers.

At Thursday lunchtime I chaired the ‘Best of GISRUK’ session, which showcased the three best papers from this year’s GISRUK conference in Bristol. It was a joint session from GISRUK, and the GIScience Research Group (where I am a committee member). The aim of this session was to show what GIS can do to a wider audience. The majority of people attending the RGS Conference do not use GIS on a regular basis, and may never have used it before. The idea of this session is to get these people to come along and get them excited about GIS, what it can do and hopefully spark some thoughts about how it might be useful in their research. We had a great turn out of 42 people in the session and I hope to see some of them using GIS in the future!

Best of GISRUK presenters, Adam Dennett, Jess Hepburn and Chris Larkin (L-R)

It was also a great opportunity to plug next year’s GISRUK conference, which is at the University of Birmingham. It will take place on 14th to 17th April 2026, and check out the GISRUK website for more details.

If you are new to GIS, or want to learn more about it, check out the first chapter of my book GIS: Research Methods, which is available for free. If you want to learn some practical skills, check out my GIS training material or my GIS training courses coming up over the next few months. If you have any questions, please contact me.

by Nick Bearman at August 31, 2025 11:00 PM

August 30, 2025

August 29, 2025

August 28, 2025

August 27, 2025

Reinder spotted this series of posters on the Rue Piat in the 20th Arrondissement of Paris.

The heading of the map translates (according to Google as “The Seine’s upheavals – watershed, living basin” – would love to know what Greendock is that needs to be stopped if any of our French followers can provide more conetxt.

The Living Basin – Is that a giant mosquito with a hook?

Whatever the Gonesse Triangle is, it gets a Yes.

But the Mega Canal is a no thank you.

by Steven at August 27, 2025 09:00 AM

August 26, 2025