Monthly Archives: February 2022

Consuming a RESTful Web Service in Spring Boot using RestTemplate

How to consume a RESTful Web Service in Spring Boot? If you have checked spring.io, they have a guide on how to use it but unfortunately, the API is unable to access during I tried the example. Therefore, this blog post will use an alternative quote API using a similar approach.

This tutorial will build an application by using Spring’s RestTemplate to retrieve a random quote from https://api.quotable.io/random. We will use Visual Studio Code as our text editor, JDK 1.8 or later, and Maven. Please make sure Java has been setup correctly, then Extension Pack for Java and Spring Initializr Java Support extensions for VS code have been installed too (the publisher of the extensions is Microsoft).

Press Ctrl+Alt+P to run the VS Code Command Palette:

  1. Type Spring Initializr and then select Spring Initializr: Create a Maven Project…
  2. Specify Spring Boot version, normally default will do
  3. Specify project language: Java
  4. Group Id: com.example.consumingrest
  5. Artifact Id: ConsumingRest
  6. Packaging type: Jar
  7. Java version: 8+
  8. Dependencies: Spring Web
  9. Lastly, select a destination folder you want to project file extract to.

We will get the RESTful service by using https://api.quotable.io/random and it can be browsed using a web browser. The JSON document will look something like this:

{
    "_id": "w0fjvau7GwbH",
    "tags": [
        "famous-quotes"
    ],
    "content": "All is flux; nothing stays still.",
    "author": "Heraclitus",
    "authorSlug": "heraclitus",
    "length": 33,
    "dateAdded": "2019-10-12",
    "dateModified": "2019-10-12"
}

We will create a domain class (src/main/java/com/example/consumingrest/Quote.java) that contains the fields for the JSON object.

package com.example.consumingrest;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Quote {
    @JsonProperty("_id")
    private String _id;
    @JsonProperty("content")
    private String content;
    @JsonProperty("author")
    private String author;
    @JsonProperty("authorSlug")
    private String authorSlug;
    @JsonProperty("length")
    private int length;
    @JsonProperty("tags")
    private String[] tags;

    public Quote() {
    }

    public String get_Id() {
        return _id;
    }

    public void set_Id(String _id) {
        this._id = _id;
    }

    public String get_Content() {
        return content;
    }

    public void set_Content(String content) {
        this.content = content;
    }

    public String get_Author() {
        return author;
    }

    public void set_Author(String author) {
        this.author = author;
    }

    public String get_AuthorSlug() {
        return authorSlug;
    }

    public void set_AuthorSlug(String authorSlug) {
        this.authorSlug = authorSlug;
    }

    public int get_Length() {
        return length;
    }

    public void set_Length(int length) {
        this.length = length;
    }

    public String[] get_Tags() {
        return tags;
    }

    public void set_Tags(String[] tags) {
        this.tags = tags;
    }

    @Override
    public String toString() {
        return "@Value {" +
            "_id=" + _id +
            ", content=" + content +
            ", author=" + author +
            ", authorSlug=" + authorSlug +
            ", length=" + length +
            ", tags=" + tagsToString() + '\'' +
            "}";
    }

    private String tagsToString() {
        StringBuilder sb = new StringBuilder();
        for (String string : tags) {
            sb.append(string + ", ");
        }
        return sb.substring(0, sb.length() - 2);
    }
}

Then, we will use a RestTemplate as a synchronized web client to perform requests to the API and it will use the Jackson JSON processing library to process the API Data.

// src/main/java/com/example/consumingrest/ConsumingRestApplication.java
package com.example.consumingrest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class ConsumingRestApplication {
	// Logger to output result to console
	private static final Logger log = LoggerFactory.getLogger(ConsumingRestApplication.class);

	public static void main(String[] args) {
		SpringApplication.run(ConsumingRestApplication.class, args);
	}

	@Bean
	public RestTemplate restTemplate(RestTemplateBuilder builder) {
		return builder.build();
	}

	@Bean
	public CommandLineRunner run(RestTemplate restTemplate) throws Exception { // Runs the RestTemplate
		return args -> {
			Quote quote = restTemplate.getForObject("https://api.quotable.io/random", Quote.class);
			log.info(quote.toString());
		};
	}

}

Finally, just hit Run Java / Debug Java using the Run or Debug button on the top right of VS Code. Alternatively, you can use this command ./mvnw spring-boot:run to execute it without debug function.

The sample result is as below:

2022-02-13 12:07:54.979  INFO 11731 --- [           main] c.e.c.ConsumingRestApplication           : No active profile set, falling back to default profiles: default
2022-02-13 12:07:57.873  INFO 11731 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-02-13 12:07:57.908  INFO 11731 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-02-13 12:07:57.909  INFO 11731 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-02-13 12:07:58.130  INFO 11731 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-02-13 12:07:58.131  INFO 11731 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2958 ms
2022-02-13 12:07:59.317  INFO 11731 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-02-13 12:07:59.349  INFO 11731 --- [           main] c.e.c.ConsumingRestApplication           : Started ConsumingRestApplication in 5.661 seconds (JVM running for 6.724)
2022-02-13 12:08:01.327  INFO 11731 --- [           main] c.e.c.ConsumingRestApplication           : @Value {_id=eDIMF-N3ATJ3, content=Let your hook always be cast; in the pool where you least expect it, there will be a fish., author=Ovid, authorSlug=ovid, length=90, tags=famous-quotes'}

Reference:
https://spring.io/guides/gs/consuming-rest/
https://github.com/lukePeavey/quotable#get-random-quote

Sample project repository:
https://github.com/sanme98/gs-consuming-rest

[.NET Core] System.Net.Sockets.SocketException (10013): An attempt was made to access a socket in a way forbidden by its access permissions.

If you get the error message below during you start a .NET Core web application or run the web app using Visual Studio Kestrel for this line of code CreateHostBuilder(args).Build().Run();, quite likely it was due to the same port number have been bound to another application.

System.Net.Sockets.SocketException (10013): An attempt was made to access a socket in a way forbidden by its access permissions.
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionListener.Bind()
   at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportFactory.BindAsync(EndPoint endpoint, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.<>c__DisplayClass21_0`1.<<StartAsync>g__OnBind|0>d.MoveNext()

The possible solution can be to turn off the application that currently occupies the same port or you can change the .NET Core Web application port using launchSettings.json > applicationUrl (it located inside Properties folder if you are using Visual Studio).

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:53627",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "TestSocketException": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5001",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

Different Types of useEffect in React Hooks

If you are using React Hooks, you will find useEffect is a quite common keyword you will see in the JSX code. However, many are not clear that useEffect has different types of usage and different types actually do different things. As per definition from the official documentation,

The Effect Hook lets you perform side effects in function components

So, what are the side effects? Before we start to explain, let’s see the anatomy of useEffect, and then we go to the four different types of useEffect.

useEffect(() => {   
  return () => {
    // Return is optional
  }
}, [Dependencies]); 
// Dependencies is optional and it can be an empty array [] also

1. Run only one time on component mount

useEffect(() => {

}, []); // An empty array []

This is the first type of the useEffect in React is it runs only one time on the component mount. It is like componentDidMount in classic React or Page_Load in .NET WebForm.

2. Run on every update

useEffect(() => {  
  
}); // Without any dependencies or an empty array []

The second type is it will run on every component update such as state changes. It is similar to componentDidUpdate in classic React.

3. Run if the dependency changes

useEffect(() => {  

}, [Dependency1, Dependency2]); // Dependencies

The third type is similar to the second type above, just its limits to the dependencies inside the array we specify. Please note the dependency can be one or more, it just needs to be separated with a common.

4. Run on unmount

useEffect(() => {  
  return () => {
    //Run on unmount
  }
}, []);

The last type is it runs during component unmount. It is similar to componentWillUnmount in classic React or Page_Unload on .NET WebForm.

Hopefully, with these four different types of useEffect explanation, we will be clearer on how to use useEffect correctly.