Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Final Release #44

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
# Backend [Places-Microservice-Server]
[![Build Status](https://travis-ci.com/climatetree/places-microservice.svg?branch=develop)](https://travis-ci.com/climatetree/places-microservice)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=com.climatetree%3Aplaces-microservice&metric=alert_status)](https://sonarcloud.io/dashboard?id=com.climatetree%3Aplaces-microservice)

# Microservice Architecture
## Repo Structure
This repository holds the source code for the backend services for locations/places included included the
climateTree.wiki web application. This application was built using Java, Maven, and Spring Boot.
This repo contains the following important folders:
- Controller
- Hosts the API endpoints
- Dao
- Provides queries that can be called on the connected database.
- All queries return a GeoJson object string.
- Services
- Intermediary class between the Controller and the Dao that performs additional data processing
steps.

The Model and DTO folders are not currently in use, but were kept for archiving purposes.

## API Endpoints
It is important to note that only 1 of the 4 APIs is currently being used in the climateTree.wiki project. The
only API that is being used is `/api/v1/places/{name}`. This is being used by the front end to retrieve the names
of places that contain the given `name`. All other APIs have been transition to GeoServer. The GeoServer repository
can be viewed [here](https://github.com/climatetree/geoserver-docker).

The endpoints that are defined in the Controller can be viewed [here on Postman](https://documenter.getpostman.com/view/10295047/Szf55VXU?version=latest)

## Database
This application directly connects to the ClimateTree project's Places Database that is currently hosted
on Azure. Connection strings are provided as environment variables to the `application.properties` configuration. The
database schema can be seen [here](https://tinyurl.com/yaa3rfp3).

## Bugs, Enhancements, and Improvements




Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

/**
* Main entry point for the application.
*/
@SpringBootApplication
@EnableCaching
public class PlacesMicroserviceServerApplication {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
import com.climatetree.places.service.NamesService;
import com.climatetree.places.service.PlacesService;

/**
* Class that defines all of the API endpoints for the Places backend microservice.
*/
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*")
@CrossOrigin(origins = "https://climatetree-api-gateway.azurewebsites.net")
public class PlacesController {

@Autowired
Expand All @@ -28,11 +31,36 @@ public class PlacesController {
@Autowired
NamesService namesService;

/**
* This endpoint returns a list of places as a GeoJson object that are similar to the place
* with the given placeId. A place is similar if it is within 95%-150% population of the provided
* place.
*
* @param placeId integer
* @return GeoJson list of places
*/
@GetMapping("/v1/places/{placeId}/similar")
public String getSimilarPlaces(@PathVariable("placeId") int placeId) {
return placesService.getSimilarPlacesDefault(placeId);
}

/**
* This endpoint returns a list of places as a GeoJson object that are similar to the place
* with the given placeId. This is an advanced filter for similar searching which means that all
* places that are returned are within every range that are provided from the user. All ranges
* are optional.
*
* @param placeId int
* @param populationStart low value of population range
* @param populationEnd high value of the population range
* @param carbonStart low value of carbon range
* @param carbonEnd high value of carbon range
* @param perCapCarbonStart low value of per capita carbon range
* @param perCapCarbonEnd high value of per capita carbon range
* @param popDensityStart low value of population density range
* @param popDensityEnd hig value of population density range
* @return GeoJson list of places
*/
@GetMapping("/v1/places/{placeId}/similar/advanced")
public String getSimilarPlaces(@PathVariable("placeId") int placeId,
@RequestParam(required = false) Integer populationStart,
Expand All @@ -47,11 +75,27 @@ public String getSimilarPlaces(@PathVariable("placeId") int placeId,
carbonEnd, perCapCarbonStart, perCapCarbonEnd, popDensityStart, popDensityEnd);
}

/**
* THIS IS THE ONLY API THAT IS CURRENTLY BEING USED ON THE FRONT END.
*
* This endpoint returns a list of places that contain the provided name. For example if the given
* name is 'Man', any place in the database that has a name that contains "man", will be returned.
* @param name serach term
* @return GeoJson list of places
*/
@GetMapping("/v1/places/{name}")
public String getPlacesByName(@PathVariable("name") String name) {
return namesService.getPlacesBySearchTerm(name);
}

/**
* This endpoint returns a single place that is closest (in geographical location) to the given
* latitude/longitude point.
*
* @param latitude latitude in degrees
* @param longitude longitude in degrees
* @return GeoJson object containing 1 place
*/
@GetMapping("/v1/places/nearest")
public String getNearestPlace(@RequestParam double latitude, @RequestParam double longitude){
return placesService.getNearbyPlace(latitude, longitude);
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/com/climatetree/places/dao/NameRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
@Repository
public interface NameRepository extends CrudRepository<Name, Integer> {

/**
* Calls a stored function in the database to return a list of GeoJson objects that contain
* the provided searchTerm.
*
* @param upperName Search term
* @return GeoJson list of places
*/
@Query(value = "SELECT public.\"getPlacesBySearchTerm\"(\n" +
"\t:upperName\n" +
")", nativeQuery = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ public interface PlaceRepository extends CrudRepository<PlaceInfo, Integer> {


/**
* Queries the database for PlaceInfo entries that are within the following range:
* Uses a stored database function to query the database and return a geoJson object where each
* Place in the list fits the following criteria:
* - TypeId = TypeId
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/climatetree/places/dto/PlaceDTO.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.climatetree.places.dto;

/**
* Defines a Places data transfer object.
*/
public class PlaceDTO {

private int placeId;
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/climatetree/places/model/EcoName.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

import com.fasterxml.jackson.annotation.JsonIgnore;

/**
* Mirrors the Eco Name table from the database.
*/
@Entity
@Table(name="\"ECO_NAME\"")
public class EcoName implements Serializable {
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/climatetree/places/model/Name.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

import com.fasterxml.jackson.annotation.JsonManagedReference;

/**
* Mirrors the Name table from the database.
*/
@Entity
@Table(name = "\"NAME\"")
public class Name implements Serializable {
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/climatetree/places/model/PlaceInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
import com.climatetree.places.dto.PlaceDTO;
import com.fasterxml.jackson.annotation.JsonBackReference;

/**
* Defines the PlaceInfo object which is based off the PlaceInfo table in the database. This class
* definition does NOT contain all fields in teh PlaceInfo db table. It only contains a small
* subset of the data.
*/
@Entity
@Table(name = "\"PLACE_INFO\"")
public class PlaceInfo implements Serializable {
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/climatetree/places/model/Type.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

import com.fasterxml.jackson.annotation.JsonIgnore;

/**
* Mirrors the Type table from the database.
*/
@Entity
@Table(name = "\"TYPE\"")
public class Type implements Serializable {
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/climatetree/places/model/WwfMhtnam.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

import com.fasterxml.jackson.annotation.JsonIgnore;

/**
* Mirrors the wwfmhtnam table from the database.
*/
@Entity
@Table(name = "\"WWF_MHTNAM\"")
public class WwfMhtnam implements Serializable {
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/climatetree/places/model/WwfRealm2.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

import com.fasterxml.jackson.annotation.JsonIgnore;

/**
* Mirrors the wwfrealm2 table from the database.
*/
@Entity
@Table(name = "\"WWF_REALM2\"")
public class WwfRealm2 implements Serializable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ public class NamesService {
@Autowired
NameRepository namesRepo;

/**
* Function that takes the provided place, changes it to all uppercase and calls the repository function
* to find places that contain the given search term.
*
* @param name search term
* @return GeoJson list of places
*/
@Cacheable(value="places")
public String getPlacesBySearchTerm(String name) {
return namesRepo.getPlacesBySearchTerm(name.toUpperCase());
Expand Down
24 changes: 19 additions & 5 deletions src/main/java/com/climatetree/places/service/PlacesService.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,22 @@ public class PlacesService {
@Value("${default_population_end}")
private int defaultEnd;


/**
* Find a single Place from the database with the provided placeId.
*
* @param placeId place Id
* @return PlaceInfo object
*/
public PlaceInfo findPlaceById(int placeId) {
Optional<PlaceInfo> placesOp = placesRepo.findById(placeId);
return placesOp.isPresent() ? placesOp.get() : null;
}

/**
* Find all Place from the database.
*
* @return List of PlaceInfo objects
*/
public List<PlaceInfo> findAllPlaces() {
List<PlaceInfo> places = new ArrayList<>();
placesRepo.findAll().forEach(p -> places.add(p));
Expand All @@ -41,7 +51,7 @@ public List<PlaceInfo> findAllPlaces() {

/**
* Returns places that adhere to all of the following constraints when compared
* to the given place: 1. Between percentStart and percentEnd of the given place's population 2.
* to the given place: 1. Between 95% and 150% of the given place's population 2.
* Is the same type (nation, state, county, or urban extent) as the given place.
*
* @param placeId the placeId of a Place
Expand All @@ -64,11 +74,15 @@ public String getSimilarPlacesDefault(int placeId) {

/**
* Returns places that adhere to all of the following constraints when compared
* to the given place: 1. Between percentStart and percentEnd of the given place's population 2.
* Is the same type (nation, state, county, or urban extent) as the given place.
* to the given place:
* 1. Between percentStart and percentEnd of the given place's population
* 2. Between carbonStart and carbonEnd of the given place's carbon
* 3. Between perCapCarbonStart and perCapCarbonEnd of the given places per capita carbon.
* 4. Between popDensityStart and popDensityEnd of the given places population density.
* 5. Is the same type (nation, state, county, or urban extent) as the given place.
*
* @param placeId the placeId of a Place
* @return a list of PlaceDTO objects that are "similar" to the given PlaceDTO
* @return a GeoJson string listing all matching places
*/
public String getSimilarPlacesAdvanced(int placeId, Integer popStart, Integer popEnd,
Integer carbonStart, Integer carbonEnd, Integer perCapCarbonStart,
Expand Down