In this post, you will see how to call an external API to build a jokes client in Java spring boot with RestTemplate. The original source of the jokes is an external API, that has an endpoint to return random Chuck Norris jokes. Chuck Norris jokes, always seem to get at least a chuckle when anyone mentions them. Using the WebClient is a newer approach better suited to asynchronous calls, however to start off, in this post you will be using the RestTemplate to call an external API. Read on this post to find the full source code as well a link to the Github repository where this class is taken from.

Java spring boot with RestTemplate

This class is a component that fetches Chuck Norris jokes from the site Chuck Norris Jokes Api that has endpoints to not only fetch random jokes but to also get jokes based on a set of categories.

import com.mydaytodo.web.backend.config.KeyConfig;
import com.mydaytodo.web.backend.models.ChuckNorrisJoke;
import jdk.jfr.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Logger;

@Component
public class JokesClient {
    private final Logger logger = Logger.getLogger(JokesClient.class.toString());
    @Autowired
    private KeyConfig config;
    private final Set<String> jokeCategories = new HashSet<>();

    public JokesClient() {
    }

    /**
     * retrieve random Chuck Norris Joke
     * @return
     */
    public ResponseEntity<ChuckNorrisJoke> getJokes() {
        RestTemplate template = new RestTemplate();
        /* config.getJokesUrl() = https://api.chucknorris.io/jokes/random */
        String url = config.getJokesUrl() + "/random";
        return template.getForEntity(url, ChuckNorrisJoke.class);
    }

    /**
     *
     * @param category
     * @return
     * @throws InterruptedException
     */
    public ResponseEntity<ChuckNorrisJoke> getJokes(String category) throws InterruptedException {
        RestTemplate template = new RestTemplate();
        loadCategories();
        if(category == null) {
            Random r = new Random();
            int index = r.nextInt(this.jokeCategories.size());
            category = jokeCategories.stream().toList().get(index);
        } else {
            // do some validation here to check for category
            String finalCategory = category;
            long count = jokeCategories.stream()
                    .filter(cat -> cat.equalsIgnoreCase(finalCategory))
                    .count();
            if (count < 1) {
                throw new InterruptedException("Invalid category passed");
            }
        }
        String url = config.getJokesUrl() + "/random?category=" + category;
        return template.getForEntity(url, ChuckNorrisJoke.class);
    }


    private void loadCategories() throws InterruptedException {
        String url = config.getJokesUrl() + "/categories";
        RestTemplate template = new RestTemplate();
        ResponseEntity<String> resp = template.getForEntity(url, String.class);
        String cats = resp.getBody();
        if(cats != null) {
            jokeCategories.addAll(Arrays.asList(cats.split("\n")));
        }
    }
}

The above class is has the following code follows,

  1. Declare a map of categories to check categories against
  2. getJokes() method gets any random joke on Chuck Norris
  3. ChuckNorris jokes will be mapped to the Java class ChuckNorrisJoke
    • ChuckNorrisJoke class to be shared later
  4. loadCategories() fetches the categories from the /categories endpoint
  5. getJokes(String category) fetches jokes based on the cateory
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;

@Getter
@Setter
@NoArgsConstructor
public class ChuckNorrisJoke {
    private String [] categories;
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    @JsonProperty("created_at")
    private Date createdAt;
    @JsonProperty("icon_url")
    private String iconUrl;
    private String id;
    @JsonProperty("updated_at")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    private Date updatedAt;
    private String url;
    private String value;
}

And

Conclusion

Hope you found this blogpost useful and you can find the full source code for this repo here on Github which also has instructions to setup and run this repo. You can view more info on the Chuck Norris Jokes API over here.

If you find any of my posts useful and want to support me, you can buy me a coffee 🙂

https://www.buymeacoffee.com/bhumansoni

While you are here, maybe try one of my apps for the iPhone.

Products – My Day To-Do (mydaytodo.com)

Have a read of some of my other posts on AWS

Deploy NodeJS, Typescript app on AWS Elastic beanstalk – (mydaytodo.com)

How to deploy spring boot app to AWS & serve via https – My Day To-Do (mydaytodo.com)

Some of my other posts on Javascript …

What is Javascript event loop? – My Day To-Do (mydaytodo.com)

How to build a game using Vanilla Javascript – My Day To-Do (mydaytodo.com)

Vanilla Javascript: Create Radio Buttons (How-To) – Bhuman Soni (mydaytodo.com)

Java Spring Boot & Vanilla Javascript solution – My Day To-Do (mydaytodo.com)

Vanilla Javascript: Create Radio Buttons (How-To) – Bhuman Soni (mydaytodo.com)

Categories: Java

0 Comments

Leave a Reply

Avatar placeholder
Verified by MonsterInsights