Create a rest-api with the Spring Boot Java framework, part two

Hi. In the previous post I showed one way to get a Spring Boot project up and running. Then added a single endpoint to display some text.

The source code for this project is available from github.

Now we’ll connect to a postgresql-server. I chose postgresql because I am familiar with it but mysql would work just as well. I use JPA and Hibernate to abstract the database.
Configuring Spring Boot to use postgresql it very easy. This guide was helpful.

Add the following code to pom.xml for postgresql. And to prepare Spring Boot for the rest-protocol. I forgot to select this during the initial configuration of the program.

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-rest</artifactIdd>
</dependency>

Spring Boot should download any dependencies automatically. Then add the following lines to the file application.properties. If you don’t use a password you can omit the third line.


spring.datasource.url= jdbc:postgresql://localhost:5432/worldcities
spring.datasource.username=worldcities
spring.datasource.password=postgres@123

Just make sure postgresql have been installed and configured. I use macports on os x, others use homebrew.

Then we’re ready to add our first class called City. This is not the complete class, constructors and getters are not included for brevity. Other than that it includes the @Entity and @Table annotation to tell Spring Boot what the table in the database looks like.

I have an old habit of using lowercase names for table names. And class names start, as an convention, with an uppercase letter and would look for a table called City if I didn’t override it in @Table.


@Entity
@Table(name = "city")
public class City implements Serializable {
    
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", columnDefinition = "serial")
    private final Integer id;
    private final String countrycode;
    private final String name_lowercase;
    private final String name;
    private final String region;
    private Integer population;
    private Float latitude;
    private Float longitude;
}

You define the endpoints for the rest-api in CityController. Lets define an endpoint to get a cityname.

@Autowired
private CityRepository cityInterface;

@RequestMapping(value = "/city/{name}", method = RequestMethod.GET)
public List<City> cityByName(@PathVariable("name") String name) {
 return cityInterface.findByName(name);
}

The database-calls are handled via the interface defined in CityRepository.

public interface CityRepository extends CrudRepository<City, Long> {
 List<City> findByName(String name);
}

So pretty easy to follow it turns out. Extract the cityname  from the path with @PathVariable and assign it to the string variable name. The call to findByName() returns zero or more City objects in a ArrayList.

I had an issue with a null-pointer exception when I called findByName() without @Autowired prepended to the CityRepository interface. I’m not sure why since it was not mentioned in the examples I looked at on the Spring Boot site. After some digging a Stackoverflow thread helped.

To get cities/locations within a radius I add the endpoint /cities/latitude/longitude/radius.

@RequestMapping(value = "/cities/{latitude}/{longitude}/{radius}", method = RequestMethod.GET)
public List<City> cityByLatitudeLongitudeRadius(
 @PathVariable("latitude") String latitude,
 @PathVariable("longitude") String longitude,
 @PathVariable("radius") String string_radius)
{}

First I define a variable with a default value for latitude, longitude and radius. And try to parse the string. Then call get_locations() that returns a List<City>.

Float lat = (float) 61.7428745;

try {
 lat = Float.parseFloat(latitude);
} catch (NumberFormatException e) { }

return get_locations(lat, lng, radius);

In get_locations() I use SimpleLatLng to calculate the latitude west and east and longitude south and north of the center. Then select all locations with this square. And lastly iterate through this list and remove locations outside the radius and return the remaining items.

List<City> cities = cityInterface.findByLatitudeBetweenAndLongitudeBetween(lat_west, lat_east, lng_south, lng_north); 

for (Iterator<City> iterator = cities.iterator(); iterator.hasNext();) {
 City city = iterator.next(); 
 LatLng p = new LatLng(city.getLatitude(), city.getLongitude());
 double d = LatLngTool.distance(center, p, LengthUnit.KILOMETER);
 if (d > radius) {
 iterator.remove();
 }
}

return cities;

 

Create a rest-api with the Spring Boot Java framework

Here is an example on how to write a simple rest-api using the Spring Boot Java framework. This first post will get you up and running with a simple hello spring page. The next post will go into detail on how to add endpoints and code to access the database, parse the result and return it as json.

The source code is available on my github-page with a tiny description which assumes how to assemble the parts.

Lately we have seen some pretty awesome Java frameworks like Jooby and SparkJava that gets you up and running in a few minutes. This is great since Java thus becomes a viable alternative to web frameworks written in javascript, ruby, php etc.

Spring Boot is almost as easy to get started with as Jooby and SparkJava. And being such a capable framework it’s remarkable how easy Pivotal, the company behind the Spring projects, have made the process that gets you there.

I’ll outline the steps I took to put together this simple rest-api. It can search for cities/locations within a radius specified by latitude and longitude. I found many good examples in Spring Boots getting-started guides and the web and Stackoverflow is a great help when issues arises.

The guides show how to create the folders and the file pom.xml. This is the build-file maven use. You can also go to Springs starter page where you can select database, functionality etc. Download and unzip and start coding.

For this project I’ll show mostly the latter and also show how to edit pom.xml to add extra functions I forgot to select rest-functionality so this will show how to add it to pom.xml. And that is nowhere near fatal if some desired functionality is left out in the beginning.

Hab kein angst. Nur viel spaß.

 

First head over to Springs starter page.

springboot01

 

Click at the link at the bottom to expand to the full version.

springboot02

 

Select Cache and DevTools. The latter is nice during development since it reloads your code on changes. This way you don’t have to stop and start your web-server on changes.

springboot03

 

Then select JPA, JDBC and Postgresql.

springboot04

 

Then click on Generate Project and your file is being downloaded.

springboot05

 

I use Eclipse as my IDE. It has it’s quirks but I like the way it tries not to be too helpful while still give some good advice when I make mistakes. Other nice IDE’s are IntelliJ and Netbeans. You decide.

You can also edit the files using an editor and run the maven project from the command line.

Import the folder into Eclipse from File->Open Projects from File System.

springboot06

 

After import the main-function is ready to run.

springboot07

 

From now on you can either start the program from the command line using “mvn spring-boot:run” or add a run-configuration to Eclipse.

From the menu select Run->Run As->Maven build… and enter “spring-boot:run” in Goals. Just remember to select Maven build with the three dots (…).

springboot08

 

Then select the Source tab and click Add…

springboot09

 

Select the project worldcities and click OK.

springboot11

 

When you get back to the previous windows mark the Default folder and click remove so we are left with the worldcities folder. Then click Run and the program starts. It may need to download some files the first time it is being run.

springboot12

 

To show a message from Spring Boot create the Java class CityController in Eclipse. Make sure the package name is the same. In this case no.gnome.

Add @RestController shown on line 6. Usually Eclipse will automatically import the necessary functions when annotations like this is added to the code. This annotation add functionality to the Spring Boot environment so your program can handle rest-request.

On line 9 add @RequestMapping(“/”) and create the function on line 10-12.


public String index() {
    return "Hello from Spring Boot!";
}

springboot13

 

When you save the file Spring Boot will automatically reload to include the changes. Open a browser and go to localhost:8080 and you are greeted with the hello message.

springboot14

 

In the next episode I will show how to add the parts to query and filter locations. Until then take care.