Building a Location-Based REST API with OpenStreetMap, PostGIS, and Spring Boot

Jul 22, 2025


Introduction

Location-based services are a core component of many modern applications — from delivery tracking to finding the nearest point of interest. In this tutorial, I'll walk through building a REST API in Java with Spring Boot, powered by OpenStreetMap (OSM) data stored in PostGIS (a spatial extension for PostgreSQL).

This guide gives you a working foundation for your own geospatial API, capable of handling spatial queries like "find the nearest pharmacy" or "calculate route distance between two coordinates."

Why OpenStreetMap + PostGIS + Spring Boot?

  • OpenStreetMap (OSM): Free, community-driven map data.
  • PostGIS: Adds spatial capabilities to PostgreSQL, enabling fast spatial queries.
  • Spring Boot: Provides a robust and scalable platform for REST API development.

This stack is ideal for building lightweight, performant, and maintainable geospatial services.

Preparing OSM Data with osm2pgsql

First, download regional OSM data from Geofabrik. Then install and run osm2pgsql to import it into PostgreSQL:

sudo apt install osm2pgsql
osm2pgsql -d osmdb -U postgres -H localhost --create --slim -G --hstore --tag-transform-script openstreetmap-carto.lua -C 2000 -S default.style serbia-latest.osm.pbf

This creates planet_osm_point, planet_osm_line, planet_osm_polygon, etc., populated with spatial data.

Setting Up the PostGIS Database

Enable PostGIS extensions in your database:

CREATE EXTENSION postgis;
CREATE EXTENSION hstore;

Confirm spatial columns exist, e.g.:

SELECT f_table_name, f_geometry_column, srid, type
FROM geometry_columns;

Creating a Spring Boot Project with Spatial Support

Create a Spring Boot app and add the necessary dependencies:

<!-- pom.xml -->
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
  </dependency>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-spatial</artifactId>
  </dependency>
</dependencies>

Configure your datasource in application.yml:

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/osmdb
    username: postgres
    password: secret
  jpa:
    properties:
      hibernate.dialect: org.hibernate.spatial.dialect.postgis.PostgisDialect

Implementing Location Queries

Create a JPA entity using org.locationtech.jts.geom.Point:

@Entity
@Table(name = "planet_osm_point")
public class OsmPoint {
  @Id
  private Long osm_id;

  private String name;

  @Column(columnDefinition = "geometry(Point,4326)")
  private Point way;
}

Now add a repository with a custom native query:

@Query("SELECT * FROM planet_osm_point p WHERE ST_DWithin(p.way, ST_SetSRID(ST_MakePoint(:lng, :lat), 4326), :radius) LIMIT 10")
List<OsmPoint> findNearby(@Param("lng") double lng, @Param("lat") double lat, @Param("radius") double radius);

Building the REST API Endpoints

@RestController
@RequestMapping("/api/pois")
public class PoiController {

  @Autowired
  private OsmPointRepository repository;

  @GetMapping("/nearby")
  public List<OsmPoint> getNearby(@RequestParam double lat, @RequestParam double lng, @RequestParam(defaultValue = "500") double radius) {
    return repository.findNearby(lng, lat, radius);
  }
}

This endpoint allows querying for points of interest within a radius.

Optimizing with Spatial Indexes

Make sure your spatial columns are indexed:

CREATE INDEX idx_way_point ON planet_osm_point USING GIST (way);

This significantly improves query performance for spatial filters.

Deploying Behind Apache with Reverse Proxy

Use Apache to expose only ports 80/443, proxying Spring Boot:

ProxyPass "/api" "http://localhost:8081/api"
ProxyPassReverse "/api" "http://localhost:8081/api"

Then configure UFW to allow only ports 22, 80, 443.

Conclusion and Next Steps

You now have a working foundation for a spatially-aware REST API based on open data. From here, you can:

  • Add more endpoints (e.g. routing, isochrones)
  • Integrate map front-ends (Leaflet, OpenLayers)
  • Use token-based authentication

About the author

Dejan Antanasković is a software developer with over two decades of experience in designing, developing, and maintaining robust backend and frontend systems – from scientific and geospatial applications to complex web and mobile platforms.