# Using Spring Boot with JavaFX - Using Spring Profiles

Author: [Wim Deblauwe](https://www.wimdeblauwe.com/about/) | Published: 2017-09-20 | Topics: javafx, spring-boot | Canonical: https://www.wimdeblauwe.com/blog/2017/2017-09-20-using-spring-boot-with-javafx---using-spring-profiles/

In the previous post, I showed ./blog/2017/09/18/using-spring-boot-with-javafx/\[how to get started with Spring Boot and JavaFX\].

Continuing with the same example, we are going to create a new implementation of the `CountryService` interface that talks to the [Open AQ Platform API](https://docs.openaq.org/) so the list of countries will be a lot bigger than our `HardcodedListCountryService` we have now.

## Using Retrofit

First, we add 2 dependencies in our `pom.xml` to be able to use [Retrofit](http://square.github.io/retrofit/):

```xml
<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>retrofit</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>converter-jackson</artifactId>
    <version>2.3.0</version>
</dependency>
```

Using Retrofit, we can easily get information from the API and transform it using Jackson into Java Objects.

First, we create an interface with a method for each call to the API we want to do:

```java
public interface OpenAqApi {

    @GET("countries")
    Call<OpenAqCountriesResponse> listCountries();
}
```

Next, we create objects that correspond to the returned JSON structures:

```java
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class OpenAqCountriesResponse {

    private List<OpenAqCountry> results;

}
```

and

```java
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class OpenAqCountry {

    private String code;
    private String name;

}
```

Note: We use `@JsonIgnoreProperties(ignoreUnknown = true)` to avoid having to add properties in Java for JSON fields we are not interested in anyway.

Finally, we create an `OpenAqServiceImpl` class that sets up Retrofit for our API:

```java
@Component
public class OpenAqServiceImpl implements OpenAqService {

    private final OpenAqApi api;

    public OpenAqServiceImpl() {

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor).build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.openaq.org/v1/")
                .addConverterFactory(JacksonConverterFactory.create())
                .client(client)
                .build();

        api = retrofit.create(OpenAqApi.class);
    }

    @Override
    public Set<OpenAqCountry> listCountries() {
        try {
            OpenAqCountriesResponse response = api.listCountries().execute().body();

            if (response != null) {
                return new HashSet<>(response.getResults());
            } else {
                return Collections.emptySet();
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
```

Note: The current code also logs the HTTP requests and responses. For this to work, you need an additional dependency:

```xml
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>logging-interceptor</artifactId>
    <version>3.8.0</version>
</dependency>
```

If you don’t want/need this logging, you can remove the dependency.

With all this plumbing in place, we can create our actual `CountryServiceImpl` that is quite simple:

```java
@Component
public class CountryServiceImpl implements CountryService {

    private final OpenAqService service;

    public CountryServiceImpl(OpenAqService service) {
        this.service = service;
    }

    @Override
    public Set<Country> getAllCountries() {
        return service.listCountries().stream()
                      .map(openAqCountry -> new Country(openAqCountry.getCode(), openAqCountry.getName()))
                      .collect(Collectors.toSet());
    }
}
```

## Spring profiles

However, if we now start our JavaFX application, Spring will complain that there are 2 classes that implement `CountryService` and it has no clue which one it has to inject into our controller. To solve this, we will add 2 extra annotations to the `HardcodedListCountryService`:

```java
@Component
@Profile("offline")
@Primary
public class HardcodedListCountryService implements CountryService {

    @Override
    public Set<Country> getAllCountries() {

        Set<Country> result = new HashSet<>();
        result.add(new Country("AU", "Australia"));
        result.add(new Country("BR", "Brazil"));
        result.add(new Country("BE", "Belgium"));

        return result;
    }
}
```

- `@Profile("offline")` instructs Spring to only create an instance of this class when the "offline" profile is active.
- `@Primary` instructs Spring to always give preference to this instance when autowiring

As a result, if we start the application without any argument, it will use the "online" version of the `CountryService` that uses the Open AQ API. When starting with

```
--spring.profiles.active=offline
```

as program arguments, the hardcoded list will be used without contacting the API online.

## Summary

Using Spring profiles makes it really easy to switch your dependencies depending on how you want to run the application. There are many cases where this can be useful, ranging from the API does not exist yet, the API is currently down or maybe you want to have some "nicer" data for screenshots.

_This know-how originated during the development of a [PegusApps](https://www.pegusapps.com/) project._

