45 MINUTE EXERCISE
In this lab you will learn about Spring Boot and how you can build microservices using Spring Boot and JBoss technologies. During this lab, you will create a REST API for the Catalog service in order to provide a list of products for the CoolStore online shop.
Spring Boot is an opinionated framework that makes it easy to create stand-alone Spring based applications with embedded web containers such as Tomcat (or JBoss Web Server), Jetty and Undertow that you can run directly on the JVM using java -jar. Spring Boot also allows producing a war file that can be deployed on stand-alone web containers.
The opinionated approach means many choices about Spring platform and third-party libraries are already made by Spring Boot so that you can get started with minimum effort and configuration.
The catalog-spring-boot project has the following structure which shows the components of the Spring Boot project laid out in different subdirectories according to Maven best practices:
Once loaded, you should see the following files and be able to navigate amongst the files. The components of the Spring Boot project are laid out in different subdirectories according to Maven best practices:
This is a minimal Spring Boot project with support for RESTful services and Spring Data with JPA for connecting to a database. This project currently contains no code other than the main class, CatalogApplication which is there to bootstrap the Spring Boot application.
Examine 'com.redhat.cloudnative.catalog.CatalogApplication' class
in the /projects/labs/catalog-spring-boot/src/main directory:
package com.redhat.cloudnative.catalog;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CatalogApplication {
public static void main(String[] args) {
SpringApplication.run(CatalogApplication.class, args);
}
}
The database is configured using the Spring application configuration file which is located at /projects/labs/catalog-spring-boot/src/main/resources/application.properties. Examine this file to see the database connection details and note that an in-memory H2 database is used in this lab for local development and will be replaced with a PostgreSQL database in the following labs. Be patient! More on that later.
You can use Maven to make sure the skeleton project builds successfully. You should get a BUILD SUCCESS message in the build logs, otherwise the build has failed.
To build and deploy the Catalog Service on OpenShift using the fabric8 maven plugin, which is already configured in CodeReady Workspaces,
In CodeReady Workspaces, right click on 'catalog-spring-boot'
project in the project explorer then, click on 'Commands > Build > build'
Once successfully built, the resulting jar is located in the target/ directory:
$ ls /projects/labs/catalog-spring-boot/target/*.jar /projects/labs/catalog-spring-boot/target/catalog-1.0-SNAPSHOT.jar
This is an uber-jar with all the dependencies required packaged in the jar to enable running the application with java -jar.
Now that the project is ready, let’s get coding and create a domain model, data repository, and a RESTful endpoint to create the Catalog service:
Create a new Java class named Product in the com.redhat.cloudnative.catalog package with the below code and following fields: itemId name desc and price
In the project explorer in CodeReady Workspaces,
right-click on 'catalog-spring-boot/src/main/java/com.redhat.cloudnative.catalog'
then click on 'New > Java Class'
. Enter 'Product'
as the Java class name.
package com.redhat.cloudnative.catalog;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
@Entity // (1)
@Table(name = "PRODUCT", uniqueConstraints = @UniqueConstraint(columnNames = "itemId")) // (2)
public class Product implements Serializable {
@Id // (3)
private String itemId;
private String name;
private String description;
private double price;
public Product() {
}
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Product [itemId=" + itemId + ", name=" + name + ", price=" + price + "]";
}
}
-
@Entity marks the class as a JPA entity
-
@Table customizes the table creation process by defining a table name and database constraint
-
@Id marks the primary key for the table
Spring Data repository abstraction simplifies dealing with data models in Spring applications by reducing the amount of boilerplate code required to implement data access layers for various persistence stores. Repository and its sub-interfaces are the central concept in Spring Data which is a marker interface to provide data manipulation functionality for the entity class that is being managed. When the application starts, Spring finds all interfaces marked as repositories and for each interface found, the infrastructure configures the required persistent technologies and provides an implementation for the repository interface.
Create a new Java interface named ProductRepository in com.redhat.cloudnative.catalog package and extend CrudRepository interface in order to indicate to Spring that you want to expose a complete set of methods to manipulate the entity.
In the project explorer in CodeReady Workspaces, right-click on 'catalog-spring-boot/src/main/java/com.redhat.cloudnative.catalog'
then click on 'New > Java Class
and paste the following code:
package com.redhat.cloudnative.catalog;
import org.springframework.data.repository.CrudRepository;
public interface ProductRepository extends CrudRepository<Product, String> {
}
That’s it! Now that you have a domain model and a repository to retrieve the domain model, let’s create a RESTful service that returns the list of products.
Spring Boot uses Spring Web MVC as the default RESTful stack in Spring applications. Create
a new Java class named CatalogController in com.redhat.cloudnative.catalog package with
the following content by right-clicking on 'catalog-spring-boot/src/main/java/com.redhat.cloudnative.catalog'
and
then click on 'New > Java Class'
:
package com.redhat.cloudnative.catalog;
import java.util.*;
import java.util.stream.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping(value = "/api/catalog")
public class CatalogController {
@Autowired
private ProductRepository repository;
@ResponseBody
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public List<Product> getAll() {
Spliterator<Product> products = repository.findAll().spliterator();
return StreamSupport.stream(products, false).collect(Collectors.toList());
}
}
The above REST service defines an endpoint that is accessible via HTTP GET at /api/catalog. Notice the repository field on the controller class which is used to retrieve the list of products. Spring Boot automatically provides an implementation for ProductRepository at runtime and injects it into the controller using the @Autowire annotation.
Build and package the Catalog Service using Maven by right clicking on 'catalog-spring-boot'
project in the project explorer then, click on 'Commands > Build > build'
Using Spring Boot maven plugin, you can conveniently run the application in CodeReady Workspaces and
test the endpoint. In CodeReady Workspaces, click on the run icon and then on 'spring-boot:run'
.
Tip
|
You can also run the Catalog Service in CodeReady Workspaces using the Commands Palette and then RUN > spring-boot:run |
When you see Started CatalogApplication in the logs, you can access the
Catalog REST API. Let’s test it out using curl
in a new terminal window:
$ curl http://localhost:9000/api/catalog [{"itemId":"329299","name":"Red Fedora","desc":"Official Red Hat Fedora","price":34.99},...]
You can also use the preview url that CodeReady Workspaces has generated for you to be able to test the service that is now running in the workspace directly in the browser. Append the path /api/catalog at the end of the preview url and try it in your browser in a new tab.
The REST API returned a JSON object representing the product list. Congratulations!
Stop the Inventory service by clicking on the stop icon
near run spring-boot in the Machines window.
It’s time to build and deploy our service on OpenShift.
OpenShift {{OPENSHIFT_DOCS_BASE}}/architecture/core_concepts/builds_and_image_streams.html#source-build[Source-to-Image (S2I)^] feature can be used to build a container image from your project. OpenShift S2I uses the supported OpenJDK container image to build the final container image of the Catalog Service by uploading the Spring Boot uber-jar from the target/ folder to the OpenShift platform.
Maven projects can use the Fabric8 Maven Plugin to access the OpenShift S2I for building the application container image. This maven plugin is a Kubernetes/OpenShift client and uses the REST API to communicate with OpenShift and issue commands to build, deploy and launch the application as a pod.
To build and deploy the Catalog Service on OpenShift using the fabric8 maven plugin,
which is already configured in CodeReady Workspaces, right click on catalog-spring-boot
project in the project explorer then, click on Commands > Deploy > fabric8:deploy
Tip
|
fabric8:deploy
It will cause the following to happen:
|
Once this completes, your project should be up and running. OpenShift runs the different components of the project in one or more pods which are the unit of runtime deployment and consists of the running containers for the project.
Let’s take a moment and review the OpenShift resources that are created for the Catalog REST API:
-
Build Config: catalog-s2i build config is the configuration for building the Catalog container image from the catalog source code or JAR archive
-
Image Stream: catalog image stream is the virtual view of all catalog container images built and pushed to the OpenShift integrated registry.
-
Deployment Config: catalog deployment config deploys and redeploys the Catalog container image whenever a new Catalog container image becomes available
-
Service: catalog service is an internal load balancer which identifies a set of pods (containers) in order to proxy the connections it receives to them. Backing pods can be added to or removed from a service arbitrarily while the service remains consistently available, enabling anything that depends on the service to refer to it at a consistent address (service name or IP).
-
Route: catalog route registers the service on the built-in external load-balancer and assigns a public DNS name to it so that it can be reached from outside OpenShift cluster.
You can review the above resources in the {{OPENSHIFT_CONSOLE_URL}}[OpenShift Web Console^] or using oc describe
command:
Tip
|
bc is the short-form of buildconfig and can be interchangeably used instead of it with the OpenShift CLI. The same goes for is instead of imagestream, dc instead of deploymentconfig and svc instead of service. |
$ oc describe bc catalog-s2i $ oc describe is catalog $ oc describe dc catalog $ oc describe svc catalog $ oc describe route catalog
You can see the expose DNS url for the Catalog Service in the {{OPENSHIFT_CONSOLE_URL}}[OpenShift Web Console^] or using OpenShift CLI.
$ oc get routes NAME HOST/PORT PATH SERVICES PORT TERMINATION catalog catalog-{{COOLSTORE_PROJECT}}.{{APPS_HOSTNAME_SUFFIX}} catalog 8080 None inventory inventory-{{COOLSTORE_PROJECT}}.{{APPS_HOSTNAME_SUFFIX}} inventory 8080 None
Click on the OpenShift Route of 'Catalog Service'
from the {{OPENSHIFT_CONSOLE_URL}}[OpenShift Web Console^].
Then click on 'Test it'
. You should have the following output:
[{"itemId":"329299","name":"Red Fedora","desc":"Official Red Hat Fedora","price":34.99},...]
Well done! You are ready to move on to the next lab.