Skip to content

A microservices sample application component, displaying options for a dinner dessert

Notifications You must be signed in to change notification settings

ibm-cloud-architecture/refarch-cloudnative-wfd-dessert

This branch is 30 commits ahead of, 23 commits behind master.

Folders and files

NameName
Last commit message
Last commit date

Latest commit

7344fad · Mar 27, 2018

History

30 Commits
Nov 16, 2017
Nov 16, 2017
Dec 22, 2017
Oct 30, 2017
Oct 28, 2017
Mar 27, 2018
Oct 28, 2017
Oct 30, 2017
Oct 20, 2017
Dec 22, 2017
Oct 30, 2017
Oct 30, 2017
Mar 27, 2018
Nov 15, 2017

Repository files navigation

Microservices Reference Application - What's For Dinner

Dessert Service - MicroProfile

This repository contains the Java MicroProfile implementation of the Dessert Service which is a part of microservice-based reference application called What's For Dinner that can be found in https://github.com/ibm-cloud-architecture/refarch-cloudnative-wfd

                      

  1. Introduction
  2. How it works
  3. API Endpoints
  4. Implementation
    1. Liberty app accelerator
    2. Microprofile
  5. Features and App details
  6. Building the app
  7. Running the app and stopping it
    1. Pre-requisites
    2. Locally in JVM
    3. Locally in Containers
    4. Locally in Minikube
    5. Remotely in ICP
  8. DevOps Strategy
  9. References

Introduction

This project demonstrates the implementation of Dessert Microservice. The dessert microservice retrieves the list of desserts from its data store.

  • Based on MicroProfile.
  • Integrated with the MicroService Builder.
  • Deployment options for local, Docker Container-based runtimes, Minikube environment and ICP/BMX.

How it works

Dessert Microservice serves What's For Dinner, Microservice-based reference application. Though it is a part of a bigger application, Dessert service is itself an application in turn that gets the data from data store. This service reads the data and returns it through a REST service.

Endpoints

GET     /WfdDessert/rest/health/        # Health check of the service
GET     /WfdDessert/rest/dessert/       # Returns the desserts available

Implementation

For Liberty, there is nice tool called Liberty Accelerator that generates a simple project based upon your configuration. Using this, you can build and deploy to Liberty either using the Maven or Gradle build.

Just check the options of your choice and click Generate project. You can either Download it as a zip or you can create git project.

Once you are done with this, you will have a sample microprofile based application that you can deploy on Liberty.

If you are using Liberty accelerator, look for the generated POM. It may contain unwanted dependencies. Please remove accordingly.

For our application, the following are the required dependencies which are the part of auto-generated POM. Please remove the rest of the dependencies.

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-rs-client</artifactId>
    <version>3.1.11</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.0.4</version>
    <scope>test</scope>
</dependency>

Using Liberty Accelerator is your choice. You can also create the entire project manually, but using Liberty Accelerator will make things easier.

MicroProfile is an open platform that optimizes the Enterprise Java for microservices architecture. In this application, we are using MicroProfile 1.2. This includes

You can make use of this feature by including this dependency in Maven.

<dependency>
<groupId>org.eclipse.microprofile</groupId>
<artifactId>microprofile</artifactId>
<version>1.2</version>
<type>pom</type>
<scope>provided</scope>
</dependency>

You should also include a feature in server.xml.

<server description="Sample Liberty server">

  <featureManager>
      <feature>microprofile-1.2</feature>
  </featureManager>

  <httpEndpoint httpPort="${default.http.port}" httpsPort="${default.https.port}"
      id="defaultHttpEndpoint" host="*" />

</server>

Features

  1. Java SE 8 - Used Java Programming language
  2. CDI 1.2 - Used CDI for typesafe dependency injection
import javax.inject.Inject;

public class DessertResource {

	@Inject
	Config config;

}
  1. JAX-RS 2.0.1 - JAX-RS is used for providing both standard client and server APIs for RESTful communication by MicroProfile applications.
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/rest")
public class DessertApplication extends Application {

}
import javax.ws.rs.Path;

@Path("dessert")
public class AppetizerResource {

}
  1. Eclipse MicroProfile Config 1.1 - Configuration data comes from different sources like system properties, system environment variables, .properties etc. These values may change dynamically. Using this feature, helps us to pick up configured values immediately after they got changed.

The config values are sorted according to their ordinal. We can override the lower importance values from outside. The config sources by default, below is the order of importance.

  • System.getProperties()
  • System.getenv()
  • all META-INF/microprofile-config.properties files on the ClassPath.

In our sample application, we obtained the configuration programatically. Below is the code snippet that shows it.

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;

public class AppetizerResource {

  @GET
	public Response getAllProperties(){
		Config config = ConfigProvider.getConfig();
		Dessert local = new Dessert();
		local.setMenu(Arrays.asList(config.getValue("menu", String.class)));
		local.setOrder(Integer.parseInt(config.getValue("order", String.class)));
		local.setType(config.getValue("type", String.class));
		return Response.ok(local, MediaType.APPLICATION_JSON).build();
	}
}

Building the app

To build the application, we used maven build. Maven is a project management tool that is based on the Project Object Model (POM). Typically, people use Maven for project builds, dependencies, and documentation. Maven simplifies the project build. In this task, you use Maven to build the project.

  1. Clone this repository.

    git clone https://github.com/ibm-cloud-architecture/refarch-cloudnative-wfd-dessert.git

  2. Checkout MicroProfile branch.

    git checkout microprofile

  3. cd refarch-cloudnative-wfd-dessert/

  4. Run this command. This command builds the project and installs it.

    mvn install

    If this runs successfully, you will be able to see the below messages.

[INFO] --- maven-failsafe-plugin:2.18.1:verify (verify-results) @ WfdDessert ---
[INFO] Failsafe report directory: /Users/user@ibm.com/PurpleCompute/Microprofile/WhatsForDinner/refarch-cloudnative-wfd-dessert/target/test-reports/it
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ WfdDessert ---
[INFO] Installing /Users/user@ibm.com/PurpleCompute/Microprofile/WhatsForDinner/refarch-cloudnative-wfd-dessert/target/WfdDessert-1.0-SNAPSHOT.war to /Users/user@ibm.com/.m2/repository/projects/WfdDessert/1.0-SNAPSHOT/WfdDessert-1.0-SNAPSHOT.war
[INFO] Installing /Users/user@ibm.com/PurpleCompute/Microprofile/WhatsForDinner/refarch-cloudnative-wfd-dessert/pom.xml to /Users/user@ibm.com/.m2/repository/projects/WfdDessert/1.0-SNAPSHOT/WfdDessert-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19.873 s
[INFO] Finished at: 2017-11-02T14:55:52-05:00
[INFO] Final Memory: 19M/304M
[INFO] ------------------------------------------------------------------------

Running the app and stopping it

Pre-requisites

  1. Locally in JVM

To run the What's For Dinner application locally in JVM, please complete the Building the app section.

  1. Locally in Containers

To run the What's For Dinner application locally in container, you need Docker to be locally present in your system.

  1. Locally in Minikube

To run the What's For Dinner application locally on your laptop on a Kubernetes-based environment such as Minikube (which is meant to be a small development environment) we first need to get few tools installed:

  • Kubectl (Kubernetes CLI) - Follow the instructions here to install it on your platform.
  • Helm (Kubernetes package manager) - Follow the instructions here to install it on your platform.

Finally, we must create a Kubernetes Cluster. As already said before, we are going to use Minikube:

  • Minikube - Create a single node virtual cluster on your workstation. Follow the instructions here to get Minikube installed on your workstation.

We not only recommend to complete the three Minikube installation steps on the link above but also read the Running Kubernetes Locally via Minikube page for getting more familiar with Minikube. We can learn there interesting things such as reusing our Docker daemon, getting the Minikube's ip or opening the Minikube's dashboard for GUI interaction with out Kubernetes Cluster.

  1. Remotely in ICP

To run the What's For Dinner application on IBM Cloud Private, we first need to get few tools installed:

  • Kubectl (Kubernetes CLI) - Follow the instructions here to install it on your platform.

  • IBM Cloud Private. You can find the detailed installation instructions here.

Along with these, you also need a JSON processor utility.

  • In our sample, we used Microservice Builder as our Devops strategy. To ensure continuous delivery and deployment, you need a continuous integration pipeline and Microservice Builder serves this purpose so very well. In order to take advantage of this, you need to setup the Microservice Builder pipeline. To find instructions on how to set your Microservice Builder pipeline up, click here.

Locally in JVM

  1. Now start your server.

    mvn liberty:start-server

    You will see the below.

[INFO] Starting server defaultServer.
[INFO] Server defaultServer started with process ID 41243.
[INFO] Waiting up to 30 seconds for server confirmation:  CWWKF0011I to be found in /Users/user@ibm.com/PurpleCompute/Microprofile/WhatsForDinner/refarch-cloudnative-wfd-dessert/target/liberty/wlp/usr/servers/defaultServer/logs/messages.log
[INFO] CWWKM2010I: Searching for CWWKF0011I in /Users/user@ibm.com/PurpleCompute/Microprofile/WhatsForDinner/refarch-cloudnative-wfd-dessert/target/liberty/wlp/usr/servers/defaultServer/logs/messages.log. This search will timeout after 30 seconds.
[INFO] CWWKM2015I: Match number: 1 is [11/2/17 15:01:40:925 CDT] 00000019 com.ibm.ws.kernel.feature.internal.FeatureManager            A CWWKF0011I: The server defaultServer is ready to run a smarter planet..
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 14.749 s
[INFO] Finished at: 2017-11-02T15:01:40-05:00
[INFO] Final Memory: 9M/309M
[INFO] ------------------------------------------------------------------------
  1. Now, go to your browser and access the REST endpoint at http://localhost:9080/WfdDessert/rest/dessert.

Access URL : http://<HOST>:<PORT>/<WAR_CONTEXT>/<APPLICATION_PATH>/<ENDPOINT>

In our sample application, you can get the details of the above URL as follows.

  • Since, we are running the application locally on our system, the HOST will be localhost.
  • You can get the PORT and WAR_CONTEXT from the <properties> </properties> section of our POM.
<app.name>WfdDessert</app.name>
<testServerHttpPort>9080</testServerHttpPort>
<testServerHttpsPort>9443</testServerHttpsPort>
<warContext>${app.name}</warContext>

So, PORT will be 9080 and WAR_CONTEXT will be WfdDessert.

@ApplicationPath("/rest")

In our sample, the APPLICATION_PATH will be rest.

@Path("dessert")

So, ENDPOINT to access the rest api that exposes the list of desserts is dessert.

Also, there is one more endpoint defined at HealthEndpoint.java

@Path("health")

To access the health api, replace the ENDPOINT with health. This endpoint gives the health of your application. To check this, use http://localhost:9080/WfdDessert/rest/health.

  1. If you are done accessing the application, you can stop your server using the following command.

    mvn liberty:stop-server

Once you do this, you see the below messages.

[INFO] CWWKM2001I: Invoke command is [/Users/user@ibm.com/PurpleCompute/Microprofile/WhatsForDinner/refarch-cloudnative-wfd-dessert/target/liberty/wlp/bin/server, stop, defaultServer].
[INFO] objc[45406]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/bin/java (0x1013de4c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x1014d84e0). One of the two will be used. Which one is undefined.
[INFO] Stopping server defaultServer.
[INFO] Server defaultServer stopped.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.988 s
[INFO] Finished at: 2017-11-02T15:15:06-05:00
[INFO] Final Memory: 9M/309M
[INFO] ------------------------------------------------------------------------

Locally in Containers

To run the application in docker, we first need to define a Docker file.

Docker file

We are using Docker to containerize the application. With Docker, you can pack, ship, and run applications on a portable, lightweight container that can run anywhere virtually.

FROM websphere-liberty:microProfile

MAINTAINER IBM Java engineering at IBM Cloud

COPY /target/liberty/wlp/usr/servers/defaultServer /config/
COPY target/liberty/wlp/usr/shared /opt/ibm/wlp/usr/shared/

RUN wget -t 10 -x -nd -P /opt/ibm/wlp/usr https://repo1.maven.org/maven2/net/wasdev/wlp/tracer/liberty-opentracing-zipkintracer/1.0/liberty-opentracing-zipkintracer-1.0-sample.zip && cd /opt/ibm/wlp/usr && unzip liberty-opentracing-zipkintracer-1.0-sample.zip && rm liberty-opentracing-zipkintracer-1.0-sample.zip

# Install required features if not present
RUN installUtility install --acceptLicense defaultServer

CMD ["/opt/ibm/wlp/bin/server", "run", "defaultServer"]
  • The FROM instruction sets the base image. You're setting the base image to websphere-liberty:microProfile.
  • The MAINTAINER instruction sets the Author field. Here it is IBM Java engineering at IBM Cloud.
  • The COPY instruction copies directories and files from a specified source to a destination in the container file system.
    • You're copying the /target/liberty/wlp/usr/servers/defaultServer to the config directory in the container.
    • You're replacing the contents of /opt/ibm/wlp/usr/shared/ with the contents of target/liberty/wlp/usr/shared.
  • The RUN instruction runs the commands.
    • The first instruction gets the Opentracing Zipkin feature and installs it in your server.
    • The second instruction is a precondition to install all the utilities in the server.xml file. You can use the RUN command to install the utilities on the base image.
  • The CMD instruction provides defaults for an executing container.

Running the application locally in a container

  1. Build the docker image.

docker build -t wfd-dessert:microprofile .

Once this is done, you will see something similar to the below messages.

Successfully built 8f9eccaa2bde
Successfully tagged wfd-dessert:microprofile

You can see the docker images by using this command.

docker images

REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
wfd-dessert                    microprofile        8f9eccaa2bde        16 seconds ago      377MB
  1. Run the docker image.

docker run -p 9080:9080 --name dessert -t wfd-dessert:microprofile

When it is done, you will see the following output.

[AUDIT   ] CWWKZ0058I: Monitoring dropins for applications.
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://71ce09bd69c6:9080/health/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://71ce09bd69c6:9080/jwt/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://71ce09bd69c6:9080/ibm/api/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://71ce09bd69c6:9080/metrics/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://71ce09bd69c6:9080/WfdDessert/
[AUDIT   ] CWWKZ0001I: Application WfdDessert-1.0-SNAPSHOT started in 1.107 seconds.
[AUDIT   ] CWWKF0012I: The server installed the following features: [microProfile-1.2, mpFaultTolerance-1.0, servlet-3.1, ssl-1.0, jndi-1.0, mpHealth-1.0, appSecurity-2.0, jsonp-1.0, mpConfig-1.1, jaxrs-2.0, jaxrsClient-2.0, concurrent-1.0, jwt-1.0, mpMetrics-1.0, mpJwt-1.0, json-1.0, cdi-1.2, distributedMap-1.0].
[AUDIT   ] CWWKF0011I: The server defaultServer is ready to run a smarter planet.
  1. Now, view the REST endpoint at http://localhost:9080/WfdDessert/rest/dessert.

Access URL : http://<HOST>:<PORT>/<WAR_CONTEXT>/<APPLICATION_PATH>/<ENDPOINT>

  1. Once you make sure the application is working as expected, you can come out of the process. You can do this by pressing Ctrl+C on the command line where the server was started.

  2. You can also remove the container if desired. This can be done in the following way.

docker ps

CONTAINER ID        IMAGE                      COMMAND                  CREATED              STATUS              PORTS                              NAMES
71ce09bd69c6        wfd-dessert:microprofile   "/opt/ibm/wlp/bin/..."   About a minute ago   Up About a minute   0.0.0.0:9080->9080/tcp, 9443/tcp   dessert

Grab the container id.

  • Do docker stop <CONTAINER ID> In this case it will be, docker stop 71ce09bd69c6
  • Do docker rm <CONTAINER ID> In this case it will be, docker rm 71ce09bd69c6

Locally in Minikube

Setting up your environment**

  1. Start your minikube. Run the below command.

minikube start

You will see output similar to this.

Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
  1. To install Tiller which is a server side component of Helm, initialize helm. Run the below command.

helm init

If it is successful, you will see the below output.

$HELM_HOME has been configured at /Users/user@ibm.com/.helm.

Tiller (the helm server side component) has been installed into your Kubernetes Cluster.
Happy Helming!
  1. Check if your tiller is available. Run the below command.

kubectl get deployment tiller-deploy --namespace kube-system

If it available, you can see the availability as below.

NAME            DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
tiller-deploy   1         1         1            1           1m
  1. Run the below command to add IBM helm repository

helm repo add ibm-charts https://raw.githubusercontent.com/IBM/charts/master/repo/stable/

If added, you will see the below message.

"ibm-charts" has been added to your repositories

Running the application on Minikube

  1. Build the docker image.

Before building the docker image, set the docker environment.

  • Run the below command.

minikube docker-env

You will see the output similar to this.

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/user@ibm.com/.minikube/certs"
export DOCKER_API_VERSION="1.23"
# Run this command to configure your shell:
# eval $(minikube docker-env)
  • For configuring your shell, run the below command.

eval $(minikube docker-env)

  • Now run the docker build.

docker build -t wfddessert:v1.0.0 .

If it is a success, you will see the below output.

Successfully built 9612f94ae9dc
Successfully tagged wfddessert:v1.0.0
  1. Run the helm chart as below.

helm install --name=wfddessert chart/wfddessert

Yow will see message like below.

==> v1beta1/Deployment
NAME                   DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
wfddessert-deployment  1        1        1           0          1s

Please wait till your deployment is ready. To verify run the same command and you should see the availability.

==> v1beta1/Deployment
NAME                   DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
wfddessert-deployment  1        1        1           1          1s
  1. You can access the application at http://<MinikubeIP>:<PORT>/<WAR_CONTEXT>/<APPLICATION_PATH>/<ENDPOINT>. To get the access url.
  • To get the IP, Run this command.

minikube ip

You will see something like below.

192.168.99.100
  • To get the port, run this command.

kubectl get service wfddessert-service

You will see something like below.

NAME                 CLUSTER-IP   EXTERNAL-IP   PORT(S)                         AGE
wfddessert-service   10.0.0.31    <nodes>       9080:31352/TCP,9443:31477/TCP   1m

In the above case, the access url will be http://192.168.99.100:31352/WfdDessert/rest/dessert.

Remotely in ICP

IBM Private Cloud is has all the advantages of public cloud but is dedicated to single organization. You can have your own security requirements and customize the environment as well. Basically it has tight security and gives you more control along with scalability and easy to deploy options. You can run it externally or behind the firewall of your organization.

Basically this is an on-premise platform.

  1. Includes docker container manager
  2. Kubernetes based container orchestrator
  3. Graphical user interface

You can find the detailed installation instructions for IBM Cloud Private here

Running the application on IBM Cloud Private

Before running the application, make sure you added the docker registry secret.

  • Install the jq command line JSON processor utility.

yum install -y jq

or

apt install -y jq

  • log in to the IBM Cloud Private. Login as admin user.

  • Go to admin > Configure Client.

  • Grab the kubectl configuration commands.

  • Run those commands at your end.

  • Create docker-registry secret admin.registrykey. This allows the pipeline to access the Docker registry.

kubectl create secret docker-registry admin.registrykey --docker-server=https://mycluster.icp:8500 --docker-username=admin --docker-password=admin --docker-email=null
  • Now update the service account with the image pull secret.
kubectl get serviceaccounts default -o json |jq  'del(.metadata.resourceVersion)' |jq 'setpath(["imagePullSecrets"];[{"name":"admin.registrykey"}])' |kubectl replace serviceaccount default -f -

Once you have all this, you are ready to deploy your microservice to Microservice builder on IBM Cloud private.

  • Now you have your microservice builder pipeline configured.
  • Push the project to the repository that is monitored by your micro service builder pipeline.
  • It will automatically pick the project, build it and deploy it to IBM cloud private.

To access the sample application, go to IBM Cloud Private dashboard.

  • Go to Workload > Services > wfdui and click on it.
  • You can see the service like below.

Click on the http link there. You will be redirected to the UI.

DevOps strategy

We opted Microservice Builder as our continuos delivery pipeline. It helps us to maintain the application end to end from development to production supporting continuous delivery. It helps us to develop and deploy microservice based applications. Using the pre-integrated Devops pipeline, developers can rapidly build innovative services and deploy them easily.

Microservice Builder runs on a Jenkins pipeline. Basically Jenkins runs in a docker container and it is deployed on Kubernetes using helm. This jenkins should be integrated with the Github. The repository to which you push the code should be integrated to Microservice Builder pipeline through Github. Then only Microservice Builder will be able to pick your code.

Microservice builder has an option to deploy with IBM Cloud Private. You can set IBM Private Cloud with Microservice Builder pipeline to deploy the microservices.

From IBM cloud private dashboard, you can access the MSB pipeline from your services. The jenkins pipeline is as follows.

By clicking on the name of your organization, you can find all the MSB enabled repositories here.

By clicking on the refarch-cloudnative-wfd-dessert, you can see the below screen.

If you see a blue ball there, your service is successfully built and running fine. If it red, it means you have some problems with it.

Whenever you do some changes and push the code to this repository, MSB build queue will initiate the process.

Once this is done, Jenkins slave will be called.

Then the Jenkins slave will pick up the build and initiate the process.

Then the build will begin and starts running.

Finally your service gets deployed once the build is done.

To access your service, go to IBM Cloud Private dashboard.

  • Go to Workload > Services > wfddessert-service and click on it.
  • You can see the service like below.

Click on the http link there. You will be redirected to the Server page. Append /WfdDessert/rest/dessert to the url and you will be able to see the Dessert service.

References

  1. Microservice Builder
  2. Developer Tools CLI
  3. IBM Cloud Private
  4. IBM Cloud Private Installation
  5. Microprofile

About

A microservices sample application component, displaying options for a dinner dessert

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published