Skip to main contentIBM Garage for Cloud

Inventory Micro App - Part 1

Ddevelop and deploy an example microservices application

Develop an example application with a three-tier microservices architecture and deploy it in IBM Cloud Kubernetes Service or Red Hat OpenShift on IBM Cloud using the IBM Cloud-Native Toolkit Developer Environment including its Code Patterns.

Business Need

In this guide, imagine you have completed an Enterprise Design Thinking Workshop and the result is an MVP statement that defines the desired business outcomes. Use the steps below to help deliver this MVP quickly while following Garage Method best practices.

MVP Statement

An MVP is a first hill. Here’s the hill statement for the MVP we’re going to build:

  • Who: Distribution employees in each of the regional warehouses

  • What: A secure web application that enables easy access to list of product SKU inventory levels and inventory locations

  • Wow: Make the system appealing and easy to use. Deliver it hosted on the IBM Cloud platform. Develop it quickly as a minimum viable product. Use the latest managed container runtimes and DevOps best practices to enable post MVP feature improvements. Simulate a release to a Test environment.

Architecture

We will build the Micro App using a three-tier microservices architecture. Each tier encapsulates a clean separation of concerns. Each app component will be modelled using microservices and use a number of polyglot programming languages and frameworks. Data will be stored in IBM Cloudant and the Micro App will be secured using IBM App ID.

Architecture

User interface

The Micro App’s user interface will look like this wireframe:

UI Design

Technical Requirements

The Micro App should adhere to the following technical requirements:

  • Microservices
    • Stateless
    • REST APIs
    • Polyglot
  • DevOps with CI/CD (continuous integration and continuous delivery)
    • Monitoring and logging
    • Code analysis
    • App security
  • Deployed to Red Hat OpenShift on IBM Cloud or IBM Cloud Kubernetes Service
  • Follow the Carbon Design System user experience

Guide

You will approach creating the Micro App bottom up, meaning you will start by creating the backend microservice that manages integration with the data persistence and then build out the digital channel using a backend for frontend pattern. Finally, you will add a web UI to the solution.

Prebuilt Solution

If you want to skip the guide and just get the components running, see Deploy the Inventory App solution.

Inventory Service

Setup

Create the initial project and register it with a pipeline for automated builds.

  • Create a new repository from the Spring Boot Microservice template

    You can access this template on the Code Patterns page in the Developer Dashboard.

    In order to prevent naming collisions, name the repository inventory-management-svc-{your initials}, replacing {your initials} with your actual initials.

  • Clone the new repository to your machine

  • Update the app name in package.json and push the change to the server repo

  • Log in to the cluster from the command line, then register the pipeline

    igc pipeline -n dev-{your initials}

    replacing {your initials} with your actual initials

  • Run igc credentials to get the credentials for the Jenkins instance

  • Open the pipeline to see it running

  • When the pipeline is completed, run igc ingress -n dev-{your initials}. You should see an entry for the app we just pushed. Select the entry and hit Enter to launch the browser.

  • Run the service locally

    npm start

    OR

    ./gradlew bootRun

    When the execution output says “Server started”, the app is running.

  • Open a browser to http://localhost:9080/swagger-ui.html

    This will display the Swagger UI page that provides a user interface to exercise the APIs.

Create initial components

Spring Boot uses annotations to configure the various components that will be injected into and used by the applications. A class with the @SpringBootApplication annotation is the starting point for the rest of the application components to be loaded. Additionally, a @ComponentScan annotation can be added to tell the Spring infrastructure which packages should be scanned for components.

We will start by creating the initial application component.

  • Create a class named Application in the com.ibm.inventory_management.app package.

  • Add the @SpringBootApplication and @ComponentScan annotation to the class. The @ComponentScan annotation should include com.ibm.inventory_management.*, com.ibm.cloud_garage.*, and com.ibm.health packages.

src/main/java/com/ibm/inventory_management/app/Application.java
package com.ibm.inventory_management.app;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ApplicationContext;
  • Delete application.app

  • Run the service locally. The swagger page should no longer contain the /hello API endpoint.

  • Commit and push the changes to Git.

git add .
git commit -m "Adds Application and Removes default Application class"
git push

Add StockItem controller

In Spring Boot, the @RestController annotation tells the framework that the class provides a REST interface. Additional annotations like @GetMapping are used to provide the specific configuration for the REST service.

  • Start the tests in tdd mode with npm run tdd (or ./gradlew test --continuous)

  • Add a StockItemControllerTest.java in com.ibm.inventory_management.controllers under the test folder

src/test/java/com/ibm/inventory_management/controllers/StockItemControllerTest.java
package com.ibm.inventory_management.controllers;
import org.junit.jupiter.api.DisplayName;
@DisplayName("StockItemController")
public class StockItemControllerTest {
}
  • Add the MockMvc infrastructure and create the StockItemController
src/test/java/com/ibm/inventory_management/controllers/StockItemControllerTest.java
package com.ibm.inventory_management.controllers;
import static org.mockito.Mockito.spy;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
src/main/java/com/ibm/inventory_management/controllers/StockItemController.java
package com.ibm.inventory_management.controllers;
public class StockItemController {
}
  • Add the tests for the controller behavior and make the corresponding changes to make the tests pass
src/test/java/com/ibm/inventory_management/controllers/StockItemControllerTest.java
package com.ibm.inventory_management.controllers;
import static org.mockito.Mockito.spy;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
src/main/java/com/ibm/inventory_management/controllers/StockItemController.java
package com.ibm.inventory_management.controllers;
import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
  • Start the local server
npm start

or

./gradlew bootRun
  • When the server starts, open a browser to http://localhost:9080/swagger-ui.html to view the swagger documentation. You should see the stock item entry in the list

  • Commit and push the changes to Git.

git add .
git commit -m "Adds StockItemController"
git push

Add a service for providing results

An established pattern for REST services in Spring Boot is to keep the REST controller logic simple and focused on translating from REST protocols to Javascript. The business logic for the components should be placed in a component that is given a @Service annotation.

  • Update the controller test to include returning data from the service
src/test/java/com/ibm/inventory_management/controllers/StockItemControllerTest.java
package com.ibm.inventory_management.controllers;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
src/main/java/com/ibm/inventory_management/models/StockItem.java
package com.ibm.inventory_management.models;
import java.io.Serializable;
public class StockItem implements Serializable {
private String name;
public String getName() {
return name;
src/main/java/com/ibm/inventory_management/services/StockItemApi.java
package com.ibm.inventory_management.services;
import java.util.List;
import com.ibm.inventory_management.models.StockItem;
public interface StockItemApi {
List<StockItem> listStockItems();
}
src/main/java/com/ibm/inventory_management/controllers/StockItemController.java
package com.ibm.inventory_management.controllers;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ibm.inventory_management.models.StockItem;
import com.ibm.inventory_management.services.StockItemApi;
  • At this points the tests should pass even though we haven’t provided an implementation of the service yet since we are creating a mocking the service in the unit test

  • Update the StockItem model to include the remaining fields

src/main/java/com/ibm/inventory_management/models/StockItem.java
package com.ibm.inventory_management.models;
import java.io.Serializable;
public class StockItem implements Serializable {
private String name;
private String id = null;
private int stock = 0;
private double price = 0.0;
  • Provide an implementation of the service that just returns a couple of hard-coded data values, for now. Services are denoted in Spring Boot with the @Service annotation
src/main/java/com/ibm/inventory_management/services/StockItemService.java
package com.ibm.inventory_management.services;
import static java.util.Arrays.asList;
import java.util.List;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
  • Replace the api() method in the SwaggerDocket class to restrict the swagger page to only show the /stock-items API
src/main/java/com/ibm/cloud_garage/swagger/SwaggerDocket.java
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(buildApiRequestHandler())
.paths(PathSelectors.regex(".*stock-item.*"))
.build()
.apiInfo(buildApiInfo());
}

Verify the service locally and push the changes

  • Start the application

    npm start

    or

    ./gradlew bootRun
  • Open a browser to http://localhost:9080/swagger-ui.html to see the Swagger page

  • Run the service by selecting Try it out then Execute

  • You should see the data we defined in the service in the previous section

  • Commit and push the changes to git

git add .
git commit -m "Adds StockItem service implementation"
git push
  • The pipeline should kick off and you will be able to see the running service by running igc ingress -n dev-{initials} and selecting the ingress of your service

Inventory BFF

The Inventory BFF’s role in the architecture is to act as an orchestrator between the core business services and the specific digital channel it is focused on supporting. This class article will give you more detail about the architectural pattern and the benefits. Backend for Frontend

The Inventory solution will use GraphQL for its BFF layer, which enables the API to be dynamically controlled from the client using API queries. Follow the steps below to get started.

Setup

To get the initial BFF project created and registered with a pipeline for automated builds follow these steps.

  • Create a new repository from the Typescript GraphQL Code Pattern

    • In order to prevent naming collisions, name the repository inventory-management-bff-{your initials} replacing {your initials} with your actual initials.
  • Clone the new repository to your machine

  • Run npm install to install all the package dependencies

  • Log into the cluster from the command-line then register the pipeline

    igc pipeline -n dev-{your initials}

    replacing {your initials} with your actual initials

  • When the pipeline is completed, run igc ingress -n dev-{your initials}. You should see an entry for the app we just pushed. Select the entry and hit Enter to launch the browser.

Build the controller for the REST interface

The controller provides the REST interface for our BFF. The Code Pattern uses the typescript-rest package to simplify the tasks required to create a controller.

  • Start the tests in tdd mode by running
npm run tdd
  • Create the controller test
test/controllers/stock-items.controller.spec.ts
import {Application} from 'express';
import * as request from 'supertest';
import {buildApiServer} from '../helper';
describe('stock-item.controller', () => {
let app: Application;
beforeEach(async () => {
  • Create the controller component
src/controllers/stock-items.controller.ts
import {GET, Path} from 'typescript-rest';
@Path('stock-items')
export class StockItemsController {
@GET
async listStockItems(): Promise<any[]> {
return [];
}
  • Add the controller to the controllers index.ts. (Using index.ts is a good way to manage which components are exposed by a component and provide a good way to load the modules that will be injected into other components)
src/controllers/index.ts
export * from './health.controller';
export * from './stock-items.controller';
  • Start the service to see it running
npm start
  • Open a browser to http://localhost:3000/api-docs to see the swagger page

  • Expand our service from the list, click Try it out, then click Execute

  • Push the changes we’ve made to the repository

git add .
git commit -m "Adds stock items controller"
git push

Update the controller to call a service

The pattern recommended for the REST controllers is to let it focus on translating REST protocols into javascript and to put the business logic in a separate service component.

  • Add a StockItem model that contains the values needed for the UI
src/models/stock-item.model.ts
export class StockItemModel {
id: string;
name: string;
description: string;
stock: number;
unitPrice: number;
picture: string;
manufacturer: string;
}
  • Register the model with the index.ts file in the models directory
src/models/index.ts
export * from './stock-item.model';
  • Define an abstract class to provide the interface for our API
src/services/stock-items.api.ts
import {StockItemModel} from '../models';
export abstract class StockItemsApi {
async abstract listStockItems(): Promise<StockItemModel[]>;
}
  • Add the abstract class to the index.ts file in the services directory
src/services/index.ts
export * from './stock-items.api';
  • Update the controller test to inject the service into the controller and to return the value from the service
test/controllers/stock-items.controller.spec.ts
import {Application} from 'express';
import * as request from 'supertest';
import {Container} from 'typescript-ioc';
import {buildApiServer} from '../helper';
import Mock = jest.Mock;
import {StockItemsApi} from '../../src/services';
describe('stock-item.controller', () => {
  • Update the controller to inject the service and use it
src/controllers/stock-items.controller.ts
import {Inject} from 'typescript-ioc';
import {GET, Path} from 'typescript-rest';
import {HttpError} from 'typescript-rest/dist/server/model/errors';
import {StockItemModel} from '../models';
import {StockItemsApi} from '../services';
class BadGateway extends HttpError {
constructor(message?: string) {

Create a mock service implementation

Now that we have our Controller using our API to get the data, lets create an implementation that will provide mock data for now.

  • Add a stock-items-mock.service to services
src/services/stock-items-mock.service.ts
import {Provides} from 'typescript-ioc';
import {StockItemsApi} from './stock-items.api';
import {StockItemModel} from '../models';
@Provides(StockItemsApi)
export class StockItemsMockService implements StockItemsApi {
async listStockItems(): Promise<StockItemModel[]> {
return [
  • Add the mock service to the index.ts file in the services directory
src/services/index.ts
...
export * from './stock-items-mock.service';
  • Start the service
npm start
  • Open a browser to http://localhost:3000/api-docs and execute the stock items controller. You should see the data from above returned by the service.

  • Push the changes we’ve made to the repository

git add .
git commit -m "Adds a mock service implementation"
git push

Add a GraphQL implementation of Stock Items

The GraphQL Code Pattern supports both REST and GraphQL APIs for accessing backend services. We created a REST controller to expose the results from the service and now we will do the same for GraphQL.

  • Create a stock-items GraphQL schema in the schemas directory
src/schemas/stock-item.schema.ts
import {Field, Float, Int, ObjectType} from 'type-graphql';
import {StockItemModel} from '../models';
@ObjectType()
export class StockItem implements StockItemModel {
@Field()
id: string;
@Field()
description: string;
  • Add the stock-items schema to the index.ts in the schemas directory
src/schemas/index.ts
export * from './stock-item.schema'
  • Add a ‘stock-item’ GraphQL resolver in the resolvers directory
src/resolvers/stock-item.resolver.ts
import {Query, Resolver} from 'type-graphql';
import {Inject} from 'typescript-ioc';
import {resolverManager} from './_resolver-manager';
import {StockItem} from '../schemas';
import {StockItemModel} from '../models';
import {StockItemsApi} from '../services';
@Resolver(of => StockItem)
  • Add the stock-items resolver to index.ts in the resolvers directory
src/resolvers/index.ts
export * from './stock-item.resolver';
  • Start the service
npm start
  • Verify that the that the resolver is available using the Graph QL browser provided by the Code Pattern

    • Open GraphQL Playground: http://localhost:3000
    • Run the query query { stockItems { name } }
  • Push the changes we’ve made to the repository

git add .
git commit -m "Adds a graphql interface"
git push

Create a service implementation that calls the microservice

  • Add a stock-item-service.config file in the config directory
src/config/stock-item-service.config.ts
import {Provided, Provider} from 'typescript-ioc';
const baseUrl: string = process.env.SERVICE_URL || 'localhost:9080';
const provider: Provider = {
get: () => ({
baseUrl,
})
};

The config class separates how the config is loaded from how it is used. In this case the config is simply retrieved from an environment variable but in more complex cases the value(s) can be retrived from external data sources.

  • Add the stock-item-service config to an index.ts of the config directory
src/config/index.ts
export * from './stock-item-service.config'
  • Create a stock-items service in the services directory that uses the config
src/services/stock-items.service.ts
import {Inject, Provides} from 'typescript-ioc';
import {get, Response} from 'superagent';
import {StockItemsApi} from './stock-items.api';
import {StockItemModel} from '../models';
import {StockItemServiceConfig} from '../config';
import {LoggerApi} from '../logger';
class StockItem {
  • Add stock-item.service to index.ts in the service directory
  • Remove stock-items-mock.service from index.ts
src/services/index.ts
export * from './stock-items.service';
  • Add a serviceUrl property to the values.yaml file of the Helm chart. The value of the property should match the Kubernetes service of the microservice. (For Code Pattern projects, the service name is the same as the name of the application which is that same as the name of the repository.)
chart/base/template/values.yaml
global: {}
serviceUrl: "inventory-management-svc-{your initials}:80"
...

The values.yaml file of the Helm chart defines the variables that can be provided to the template as input. Now that we’ve added a new variable, we will need to update the appropriate template file to use our new variable.

  • Add a new environment variable named SERVICE_URL to the list of existing environment variables in deployment.yaml. (SERVICE_URL is the name we gave the environment variable in our stock-item-service.config class as the first step in this section.) The value of this environment variable should come from the serviceUrl value we defined. You can add | quote to wrap the value in quotes in case the value is not formatted correctly.
chart/base/templates/deployment.yaml
...
env:
- name: INGRESS_HOST
value: {{ include "starter-kit-chart.host" . }}
- name: PROTOCOLS
value: {{ include "starter-kit-chart.protocols" . }}
- name: SERVICE_URL
value: {{ .Values.serviceUrl | quote }}
...

deployment.yaml is a templatized Kubernetes yaml file that describes the deployment of our component. The deployment will create one or more pods based on the pod template defined in the deployment. Each pod that starts will have the envionment variables that we have defined in the env section available for the container image to reference.

  • Commit and push the changes to git
git add .
git commit -m "Adds service implementation"
git push

Inventory UI

Setup

Get the initial project created and register the pipeline for automated builds. Detailed instructions for each of these steps can be found in the Deploying an App guide.

  • Create a new repository from the React UI Patterns Code Pattern into your Git org - https://github.com/ibm-garage-cloud/template-node-react/generate

    In order to prevent naming collisions, name the repository inventory-management-ui-{your initials} replacing {your initials} with your actual initials.

  • Clone the new repository to your machine

  • Run npm install to install the project dependencies

  • Log into the cluster from the command-line then register the pipeline

    igc pipeline -n dev-{your initials}

    replacing {your initials} with your actual initials

Create the initial components

The React Code Pattern comes with a set UI components that implement 12 common UI Design Patterns. In the initial UI, all of the components are included to create an interactive example of how they work. The first step of building an application with the React Code Pattern is to remove those components from the menu and to create new components built from the pattern components.

Based on the requirements of this first use case, we will create a StockItemList component based on the TableList pattern.

  • Open a terminal and start the application in development mode to see the initial UI and the changes as we make them
npm run start:dev
  • Make a copy of the TableList pattern component from the pattern-component directory into the components folder. Rename the file and the class inside to StockItemList.
client/src/components/StockItemList.jsx
import React, { Component } from "react";
import {
StructuredListWrapper,
StructuredListRow,
StructuredListCell,
StructuredListHead,
StructuredListBody,
StructuredListInput,
Icon
  • Update UIShell.jsx

    • Update the header variable to whatever name you want. “Big Blue Widgets” is used in the example
    • Update the menuTitle to “Inventory Management”
    • Remove all the values from menuItems
client/src/components/UIShell.jsx
class UIShell extends Component {
header = "Big Blue Widgets";
menuTitle = "Inventory Management";
menuItems = [
"Stock Items",
];
...
}
  • Update UIShellBody.jsx

    • Remove all of the pattern values from the components map and add one entry for Stock Item List. The value on the left is the label that is displayed and the value on the right is the class that should be loaded (e.g. "Stock Items": StockItemList). Note: The label value needs to match the one used on UIShell
    • Update the Use Stock Items as the default pattern name when none is given
client/src/components/UIShellBody.jsx
import React, {Component} from "react";
import "../pattern-components/patterns.scss";
import StockItemList from "./StockItemList";
class UIShellBody extends Component {
components = {
"Stock Items": StockItemList
};
  • With the application running in the first terminal, open a second terminal in the repository directory and push the changes we’ve made to the repository
git add .
git commit -m "Initial shell components"
git push
  • Refresh the browser from earlier (or follow the steps from before to use igc ingress to open the browser). The changes we just made should be reflected in the UI.

Update StockItemList contents

Now that we’ve created the initial components, we can start to customize the StockItemList to match the data for our application.

  • Start the application in development mode (if not already running) with npm run start:dev

  • Update the title and subtitle with values for our Stock Items view.

  • Update the columns and data fields with the list of columns and sample data to match the UI. Set the formatters to {} for now.

    The value in the columns array maps to one of the attributes in our data values (e.g. name refers to the name attribute)

  • The result of these changes should look like the following:

client/src/components/StockItemList.jsx
class StockItemList extends Component {
title = 'Stock Items';
subtitle = 'This is the current inventory of items';
columns = [
"name",
"description",
"stock",
"unitPrice",
  • View the new data in your local UI: http://localhost:3000/

  • Push the changes we’ve made to the repository

git add .
git commit -m "Updates the StockItemsList view"
git push
  • Look at the Jenkins pipeline and the deployed app

Add a service component to get mock Stock Items

So far, we’ve built a UI that displays a hard-coded set of data in a table. Eventually, we want to display dynamic data provided from a database in the table. As a first step towards that goal, we need to separate the UI logic from the logic that retrieves the data. We will do that with a service component. For this first pass the service component will just return mock data.

  • Create a directory called services under the client/src folder

  • Create a file named stock-item-mock.service.js in the service directory. Our StockItem service component will have a single asynchronous function called listStockItems() that returns a list of StockItems.

client/src/services/stock-item-mock.service.js
export class StockItemMockService {
async listStockItems() {
return [];
}
}
  • Implement the service by copying the data array from StockItemList and returning it in the function. You can add a call to timer() to simulate wait time
client/src/services/stock-item-mock.service.js
import timer from '../util/timer';
export class StockItemMockService {
async listStockItems() {
// wait 1 second before returning data
await timer(1000);
return [
{
  • Update the components to pass the service in the properties
client/src/App.test.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {StockItemMockService} from "./services/stock-item-mock.service";
describe('App', () => {
test('canary verifies test infrastructure', () => {
expect(true).toEqual(true);
});
client/src/App.jsx
import React, { Component } from "react";
import UIShell from "./components/UIShell";
import "./App.scss";
import {StockItemMockService} from "./services/stock-item-mock.service";
class App extends Component {
constructor(props) {
super(props);
client/src/components/UIShell.jsx
...
class UIShell extends Component {
...
render() {
return (
<div>
<Header aria-label="IBM Platform Name">
client/src/components/UIShellBody.jsx
...
class UIShellBody extends Component {
components = {
"Stock Items": StockItemList
};
defaultComponent = "Stock Items";
render() {
  • Update StockItemList to use the provided service
src/components/StockItemList.jsx
...
class StockItemList extends Component {
...
async componentDidMount() {
this.setState({
data: await this.props.stockService.listStockItems()
  • View the new data in your local UI: http://localhost:3000/

  • Push the changes we’ve made to the repository

git add .
git commit -m "Adds a mock service"
git push
  • Look at the Jenkins pipeline and the deployed app

Add a service that calls the BFF

Now that we have a mock service that injects data, we can build an implementation of the service that calls our BFF. For the service, we will use a package called superagent to make the calls to the BFF.

  • With npm, install the superagent and @types/superagent dependencies
npm i -s superagent
npm i -D @types/superagent
  • Create a service implementation in the services directory called stock-item.service.js
client/src/services/stock-item.service.js
export class StockItemService {
async listStockItems() {
return [];
}
}
  • Add an implementation of listStockItems() that calls the BFF through the /api proxy
client/src/services/stock-item.service.js
import * as superagent from 'superagent';
export class StockItemService {
constructor(baseUrl) {
this.baseUrl = baseUrl || '/api';
}
async listStockItems() {
return superagent

Note: In dev mode, the proxy is configured in client/package.json. When running with the express server, the proxy is configured in server/routers/api.js. By default, the value points to localhost:3001.

  • Update App.jsx to use the new service instead of the mock service.
client/src/App.jsx
import React, { Component } from "react";
import UIShell from "./components/UIShell";
import "./App.scss";
import {StockItemService} from "./services/stock-item.service";
class App extends Component {
constructor(props) {
super(props);
  • The deployment is already configured to use the value of apiHost for our proxy service. We need to configure the apiHost value to point to the Kubernetes service resource of the BFF.
chart/base/template/values.yaml
apiHost: "inventory-management-bff-{your initials}:80"
  • Push the changes we’ve made to the repository
git add .
git commit -m "Updates the StockItemsList view"
git push
  • Look at the Jenkins pipeline and the deployed app

Summary

You have now completed the Micro App Guide demonstrating the Inventory solution.

Deploy the Inventory App solution

If you were unable to get everything working, you can deploy the Inventory App solution. You may want to do this before continuing to Inventory Micro App - Part 2.

Inventory Services

Inventory BFF

  • Create a new project from the Inventory Management BFF solution template named inventory-management-bff-{initials}

  • Clone the repository to your local machine

  • Log into the cluster from the command-line then register the pipeline

    igc pipeline -n dev-{your initials}
    • replacing {your initials} with your actual initials
  • Run igc credentials to get the credentials for the Jenkins instance.

  • Update the serviceUrl value in charts/base/templates/values.yaml to point to the kubernetes service of the microservice. The value most likely will be inventory-management-svc-{initials}:80.

  • Commit and push the changes

    git add .
    git commit -m "Update the serviceUrl"
    git push

Inventory UI

  • Create a new project from the Inventory Management UI solution template named inventory-management-ui-{initials}

  • Clone the repository to your local machine

  • Log into the cluster from the command-line then register the pipeline

    igc pipeline -n dev-{your initials}
    • replacing {your initials} with your actual initials
  • Run igc credentials to get the credentials for the Jenkins instance.

  • Update the hostApi value in charts/base/templates/values.yaml to point to the kubernetes service of the BFF. The value most likely will be inventory-management-bff-{initials}:80.

  • Commit and push the changes

    git add .
    git commit -m "Update the hostApi"
    git push
  • Verify that the application is running