End to End Java Openliberty CP4Apps workflow

Recently updated to include RedHat OpenShift 4.x

Prerequisites

Add Stacks to appsody

  • From the Cloud Pak for Applications landing page get the Appsody URL, for example:

  • Use the appsody CLI to add add the URL for your stack configuration file:

appsody repo add kabanero https://github.com/kabanero-io/collections/releases/download/0.3.5/kabanero-index.yaml
  • If possible, remove other repos that are existing.

To get the list of available repos, run this command.

appsody repo list

This returns you something like below.

$ appsody repo list

NAME            URL
*incubator      https://github.com/appsody/stacks/releases/latest/download/incubator-index.yaml
experimental    https://github.com/appsody/stacks/releases/latest/download/experimental-index.yaml
kabanero        https://github.com/kabanero-io/kabanero-stack-hub/releases/download/0.6.3/kabanero-stack-hub-index.yaml

To remove the unused repos, run

appsody repo remove <NAME>

For instance, if you want to remove appsodyhub, then it will be appsody repo remove appsodyhub.

  • List the appsody stacks available in the Collection:

appsody list kabanero

It gives you the list of available stacks.

$ appsody list kabanero

REPO    	ID               	VERSION  	TEMPLATES        	DESCRIPTION
kabanero	java-microprofile	0.2.26   	*default         	Eclipse MicroProfile on Open Liberty & OpenJ9 using Maven
kabanero	java-openliberty 	0.2.3    	*default         	Open Liberty & OpenJ9 using Maven
kabanero	java-spring-boot2	0.3.24   	*default, kotlin 	Spring Boot using OpenJ9 and Maven
kabanero	nodejs           	0.3.3    	*simple          	Runtime for Node.js applications
kabanero	nodejs-express   	0.2.10   	scaffold, *simple	Express web framework for Node.js
  • Set the kabanero repo as default.

appsody repo set-default kabanero

If you want to customize the appsody stacks and extend them, refer to Customizing application stacks.

Appsody application

Create a new Application

  • Create a new directory for the project and change directory into it.

mkdir appsody_sample_openliberty

cd appsody_sample_openliberty/
  • Initialize the project using appsody init by selecting the desired stack ID template simple.

appsody init kabanero/java-openliberty
  • The directory contains a minimal set of artifacts

.
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── dev
    │   │       └── appsody
    │   │           └── starter
    │   │               ├── StarterApplication.java
    │   │               ├── StarterResource.java
    │   │               └── health
    │   │                   ├── StarterLivenessCheck.java
    │   │                   └── StarterReadinessCheck.java
    │   ├── liberty
    │   │   └── config
    │   │       ├── configDropins
    │   │       │   └── defaults
    │   │       │       └── quick-start-security.xml
    │   │       └── server.xml
    │   └── webapp
    │       ├── WEB-INF
    │       │   └── beans.xml
    │       └── index.html
    └── test
        └── java
            └── it
                └── dev
                    └── appsody
                        └── starter
                            ├── EndpointTest.java
                            └── HealthEndpointTest.java
mvnw.cmd

a Maven Wrapper for Windows environments

mvnw

a Maven Wrapper for Unix-like environments

pom.xml

a project build file

StarterApplication.java

a JAX-RS Application class

StarterResource.java

a JAX-RS Resource class

quick-start-security.xml

a simple administrative security configuration

server.xml

an Open Liberty server configuration file

index.html

a static HTML file

beans.xml

the CDI deployment descriptor

EndpointTest.java

a test for the Starter resource endpoint

HealthEndpointTest.java

tests for the readiness and liveness endpoints

Build the application

This command will locally build a docker image of your appsody project.

appsody build

Once it builds successfully, you will see something like this.

[Docker] Step 62/62 : LABEL version=0.2.3
[Docker]  ---> Running in e9306f09a5fc
[Docker] Removing intermediate container e9306f09a5fc
[Docker]  ---> 129730417f81
[Docker] Successfully built 129730417f81
[Docker] Successfully tagged dev.local/appsody-sample-openliberty:latest
Built docker image dev.local/appsody-sample-openliberty
Running command: docker create --name appsody-sample-openliberty-extract docker.io/kabanero/java-openliberty:0.2

It helps you to check that stack is stable and init is done correctly. You do not need to run build directly ever again.

Test the Application

  • Test the application using appsody

appsody test

This step is building a container and running the test command inside of it.

[Container] [INFO] ------------------------------------------------------------------------
[Container] [INFO] BUILD SUCCESS
[Container] [INFO] ------------------------------------------------------------------------
[Container] [INFO] Total time:  01:04 min
[Container] [INFO] Finished at: 2020-04-12T04:40:59Z
[Container] [INFO] ------------------------------------------------------------------------
[Container] + set +x
[Container] The file watcher is not running because no APPSODY_RUN/TEST/DEBUG_ON_CHANGE action was specified or it has been disabled using the --no-watcher flag.
Closing down development environment.

Run the Application

  • Run the application using appsody

appsody run

This step is building a container and running it, the output has the endpoint for the application.

Running development environment...
Running command: docker[pull kabanero/java-spring-boot2:0.3]
Running docker command: docker[run --rm -p 5005:5005 -p 8080:8080 -p 35729:35729 --name appsody-sample-springboot-dev -u 501:20 -e APPSODY_USER=501 -e APPSODY_GROUP=20 -v /Users/<user>@ibm.com/kabanero101/appsody_sample_springboot/.:/project/user-app -v /Users/<user>@ibm.com/.m2/repository:/mvn/repository -v /Users/<user>@ibm.com/.appsody/appsody-controller:/appsody/appsody-controller -t --entrypoint /appsody/appsody-controller kabanero/java-spring-boot2:0.3 --mode=run]
......
......
......
[Container] 2019-09-12 17:49:22.173  INFO 185 --- [  restartedMain] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 4 endpoint(s) beneath base path '/actuator'
[Container] 2019-09-12 17:49:22.377  INFO 185 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
[Container] 2019-09-12 17:49:22.386  INFO 185 --- [  restartedMain] application.Main                         : Started Main in 7.984 seconds (JVM running for 9.679)
[Container] 2019-09-12 17:58:42.777  INFO 185 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
[Container] 2019-09-12 17:58:42.777  INFO 185 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
[Container] 2019-09-12 17:58:42.805  INFO 185 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 27 ms
[Container] 2019-09-12 17:58:43.044  INFO 185 --- [nio-8080-exec-1] i.j.internal.reporters.LoggingReporter   : Span reported: 445d02b19cea491:445d02b19cea491:0:1 - GET

For more details, refer Java Openliberty Stack.

Stop the Application

  • To stop the application container, run this command.

appsody stop
  • Alternatively, you can also press Ctrl+C.

Update the Application

  • Lets add a new endpoint API to our Application

    Change the file src/main/java/dev/appsody/starter/StarterResource.java and populate with the following code:

    package dev.appsody.starter;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    @Path("/hello")
    public class StarterResource {
        @GET
        public String getRequest() {
            return "Hello World";
        }
    }
microprofile code change
microprofile hello endpoint
  • Make a change to the application and refresh the browser for example Hello World Demo

microprofile hello refresh

Debug the Application

  • Open your editor. We are using VS Code. Add the project to your workspace, or use the command code .

microprofile lab1 vscode project
  • Open a new terminal window inside VS Code. Use View→Terminal.

microprofile lab1 vscode terminal
  • To debug the application including reloading the application on code changes run the below command.

appsody debug

The output indicates the debug environment is being used.

Running debug environment
Running command: docker pull kabanero/java-microprofile:0.2
Running docker command: docker run --rm -p 7777:7777 -p 9080:9080 -p 9443:9443 --name appsody-sample-microprofile-dev -v /Users/user/.m2/repository:/mvn/repository -v /Users/user/GitHub/Cloud/Cloud-Native/Kabanero/appsody_sample_microprofile/src:/project/user-app/src -v /Users/user/GitHub/Cloud/Cloud-Native/Kabanero/appsody_sample_microprofile/pom.xml:/project/user-app/pom.xml -v /Users/user/.appsody/appsody-controller:/appsody/appsody-controller -t --entrypoint /appsody/appsody-controller kabanero/java-microprofile:0.2 --mode=debug
.......
.......
.......
[Container]  INFO  --- liberty-maven-plugin:2.6.4:debug (default-cli) @ starter-app ---
[Container]  INFO  CWWKM2102I: Using artifact based assembly archive : io.openliberty:openliberty-runtime:null:19.0.0.8:zip.
[Container]  INFO  CWWKM2102I: Using installDirectory : /project/user-app/target/liberty/wlp.
[Container]  INFO  CWWKM2102I: Using serverName : defaultServer.
[Container]  INFO  CWWKM2102I: Using serverDirectory : /project/user-app/target/liberty/wlp/usr/servers/defaultServer.
[Container]  INFO  CWWKM2112I: Re-using previously installed assembly.
[Container]  INFO  Copying 1 file to /project/user-app/target/liberty/wlp/usr/servers/defaultServer
[Container]  INFO  CWWKM2144I: Update server configuration file server.xml from /project/user-app/src/main/liberty/config/server.xml.
[Container]  INFO  CWWKM2144I: Update server configuration file bootstrap.properties from inlined configuration.
[Container]  INFO  CWWKM2001I: server.config.dir is /project/user-app/target/liberty/wlp/usr/servers/defaultServer.
[Container]  INFO  CWWKM2001I: server.output.dir is /project/user-app/target/liberty/wlp/usr/servers/defaultServer.
[Container]  INFO  CWWKM2001I: Invoke command is  /project/user-app/target/liberty/wlp/bin/server, debug, defaultServer .
[Container]  INFO
[Container]  INFO  Listening for transport dt_socket at address: 7777
  • You can attach to the debugger using VSCode

  • To access the debug view use View→Debug or click Debug icon on left menu

microprofile lab1 vscode debug
  • Add a breakpoint to the application, click to the left of the line number

microprofile lab1 vscode breakpoint
  • Click on the debug task Appsody: Attach java debugger

microprofile lab1 vscode attach
microprofile lab1 vscode attach break

Appsody tasks on VS Code

  • To access the build tasks on VS code, go to

Terminal > Run Build Task...
sb lab1 build task menu
  • You will see a list of available tasks.

sb lab1 build task list
  • Click on Appsody: run and this will run the application.

sb lab1 build task run
microprofile home

Codewind on VS Code

Codewind simplifies and enhances development in containers by extending industry standard IDEs with features to write, debug, and deploy cloud-native applications. It helps you to get started quickly with templates or samples, or you can also pull in your applications and let Codewind get them cloud ready.

Codewind supports VS Code, Eclipse Che, and Eclipse. In this lab, we are using VS Code as our IDE.

Getting the Codewind extension

  • Go to the extensions view and install codewind from the VS code market place.

sb lab1 vscode codewind extension

You will find Codewind then click install to get it. Also, if you want to use Codewind for Node.js performance analysis, you need to install Codewind Node.js Profiler.

  • Once you get them installed, let us now open the Codewind in the IDE.

View > Open View...
sb lab1 vscode view
  • It gives you you a list of options. Select Codewind.

sb lab1 vscode code explorer
  • This opens the Codewind.

sb lab1 vscode codewind explorer

If you want to configure codewind with appsody, checkout Configure CodeWind with Appsody CLI.

Adding the application

  • You can create a new project or add an existing project to Codewind. Since, we already created one using appsody earlier, let us add the existing project.

  • Right click on Projects under Codewind. Select Add Existing Project in the menu.

sb lab1 codewind add existing project
- Before doing this, copy your project to the codewind workspace. At this point in time, codewind only accepts the projects that are available in the codewind workspace.
  • From the codewind workspace, select the project you created earlier.

microprofile add
  • The codewind extension asks you for confirmation as follows. Click Yes.

microprofile confirm
  • The project will be added.

microprofile codewind starting
  • Once it is successfully built, it starts running.

microprofile codewind running

Project Options

  • Go to the application and right click on it to access the various options available.

microprofile codewind options
  • Click Open App to access the application.

microprofile codewind
- Codewind exposes your applications on different external ports. This will allow you to run multiple projects of same type.
  • To get the overview of your project, click on Open Project Overview.

microprofile overview
  • You can access the container shell directly from the IDE by using Open Container Shell.

sb lab1 codewind container shell
  • To access the logs of the application, click on Show all logs.

sb lab1 codewind project logs
  • You can also hide the logs if you want to by using Hide all logs option.

  • If you have multiple applications and want to manage the logs for them, you can use Manage logs.

  • You can also run the application by using Restart in Run Mode.

sb lab1 codewind project restart in run mode

Once it is restarted, you can access the application by clicking on the button as shown below.

sb lab1 restart in run mode app
  • Similarly, you can also do debugging by using Restart in Debug Mode.

Deploy the appsody application on Openshift for team development

Set up team project namespace

  • Create a new project for your team if it does not exist. Or if you have an existing project, skip this step.

oc new-project <yournamespace>

Once you create it, you will see something like below.

$ oc new-project kabanero-samples
Already on project "kabanero-samples" on server "https://c100-e.us-east.containers.cloud.ibm.com:31718".

You can add applications to this project with the 'new-app' command. For example, try:

    oc new-app centos/ruby-25-centos7~https://github.com/sclorg/ruby-ex.git

to build a new example application in Ruby.
  • Switch to the target project using the below command.

oc project <yournamespace>

It gives you the below message if you are already in that space.

$ oc project kabanero-samples
Already on project "kabanero-samples" on server "https://c100-e.us-east.containers.cloud.ibm.com:31718".
  • Check that the current context is your team’s project space.

oc project -q

You will see something like below.

$ oc project -q
kabanero-samples

Add new Target Namespace

  • In order to deploy you app to the new project (kabanero-samples), perform the following:

  • First check that you have kabanero available

$ oc get kabaneros -n kabanero
NAME       AGE   VERSION   READY
kabanero   44h   0.6.1     True
  • Next, we will have to edit the yaml file configuring kabanero with the following command.

  • This will bring up your default editor

$ oc edit kabanero kabanero -n kabanero
  • Finally, navigate to the spec label within the file and add the following targetNamespaces label.

spec:
  targetNamespaces:
    - kabanero-samples

Create application deployment manifest

  • Extract the appsody deployment config file

appsody build

This will generate the file app-deploy.yaml with the following content:

apiVersion: appsody.dev/v1beta1
kind: AppsodyApplication
metadata:
  name: appsody-sample-openliberty
spec:
  applicationImage: dev.local/appsody-sample-openliberty
  createKnativeService: false
  expose: true
  livenessProbe:
    failureThreshold: 12
    httpGet:
      path: /health/live
      port: 9080
    initialDelaySeconds: 5
    periodSeconds: 2
  readinessProbe:
    failureThreshold: 12
    httpGet:
      path: /health/ready
      port: 9080
    initialDelaySeconds: 5
    periodSeconds: 2
    timeoutSeconds: 1
  service:
    annotations:
      prometheus.io/scrape: "true"
    port: 9080
    type: NodePort
  stack: java-openliberty
  version: 1.0.0

By default, the application is deployed in the kabanero namespace. If you want to deploy the application in a different namespace, you can specify it in this yaml file. In this lab, let us use a namespace called kabanero-samples and we can specify it under the metadata as below.

apiVersion: appsody.dev/v1beta1
kind: AppsodyApplication
metadata:
  name: appsody-sample-openliberty
  namespace: kabanero-samples

Creating a git repo

  • Setup your git locally with the content of the application.

git init
git add .
git commit -m "initial commit"
  • Create a github repository and push the code to the remote repository.

git remote add origin $GITHUB_REPOSITORY_URL
git push -u origin master

Create an access token

  • Go to Github Settings.

  • Select Developer settings.

  • Click on Personal access tokens.

  • Select Generate new token.

  • Create a Github access token with permission admin:repo_hook

sb lab1 github token
  • Then finally click Generate token to create one.

For more details on how to generate Github personal access token refer Creating a personal access token.

Configure the DevOps Pipeline

Accessing Tekton dashboard

  • Navigate to the menu in the upper left and select instances.

  • Then click the link under the Tekton label to navigate to the Tekton Dashboard.

tekton link 42
sb lab1 tekton dashboard

Create Tekton webhook for git repo

  • Click on Webhooks in the menu.

  • Click on Add Webhook.

  • Enter the information for the Webhook settings.

sb lab1 webhook settings
Name - <Name for webhook>
Repository URL - <Your github repository URL>
Access Token - <For this, you need to create a Github access token with permission `admin:repo_hook` or select one from the list>

For more information on how to configure github credentials, refer to Tekton - Configure GitHub Credentials.

  • Create a new token as follows.

sb lab1 webhook settings access token create
  • You can also use an existing token if it is already created.

sb lab1 webhook settings access token existing

Set up the pipeline

  • Enter the information for the Pipeline settings NOTE: Replace <your_project> with the name of the target namespace in our case kabanero-samples

Namespace - kabanero
Pipeline - java-openliberty-build-deploy-pipeline
Service account - kabaner-operator
OCP 3.11 - Docker Registry - docker-registry.default.svc:5000/<your_project>
OCP 4.X - Docker Registry - image-registry.openshift-image-registry.svc:5000/<your_project>
sb lab1 pipeline settings

Here, we are using the default docker registry that comes with the openshift cluster. Sometimes, you may need to configure a third party registry instead of using the default one. In order to do that, check out Tekton - Configure External Docker Registry.

  • Click Create, a new webhook is created.

sb lab1 webhook

Also, a new Gitub webhook is created on the project repository.

You can verify it by going into your github repository > Settings > Webhooks and you should be able to see the webhook created.

Replace <your_project> with the name of the target namespace in our case kabanero-samples

Here, we are using the default pipeline. If you want to customize the pipeline, refer to Creating and updating tasks and pipelines.

Deploy the Application

The way to deploy the application is to make a change in the application in the git repository to trigger the tekton webhook and start the DevOps pipeline to build and deploy the application.

  • Make a change to the application such as changing the index.html or any other things.

Let us change the title from Hello from Appsody! to Hello from Cloud Paks !!!.

  • Push your changes to the remote git repository.

  • This will trigger the Tekton Pipeline. To see the status of the Pipeline click on PipelineRuns on the menu of the dashboard.

sb lab1 pipeline runs
  • When the application is built and deployed the application will be available via the expose Route.

OCP 3.11 Instructions

  • Go to the OpenShift Console, switch to the project, and select Applications > Routes

You will see a route for your application, click on the url to open your application.

sb lab1 application route

OCP 4.X instructions

  • Open the menu in the upper left of the OpenShift Console and navigate to Topology.

  • Select your Application in the center, and view the route(s) on the side.

  • Note: Please ensure you are in the developer role (should be default if following this guide)

dc microprofile route
  • Or you can also get the route from the oc CLI.

oc get route -n <your_project>

For instance,

$ oc get routes -n kabanero-samples
NAME                        HOST/PORT                                                                                                                                PATH      SERVICES                    PORT      TERMINATION   WILDCARD
appsody-sample-openliberty   appsody-sample-openliberty-kabanero-samples.ocp.example.com            appsody-sample-mopenliberty   8080                    None

You can now acccess the application at <HOST/PORT>, here it is appsody-sample-openliberty-kabanero-samples.csantana-ocp3-fa9ee67c9ab6a7791435450358e564cc-0001.us-east.containers.appdomain.cloud.

Add the target namespace to ServiceMeshMemberRoll

  • Edit the resource smmr :

oc edit smmr -n knative-serving-ingress
  • Append the target namespace into the SMMR resource spec for example kabanero-samples leave any other namespaces already present:

spec:
  members:
  - knative-serving
  - kabanero-samples
  • Verify the namespace kabanero-samples was added by following this command:

oc get smmr default -n knative-serving-ingress -o jsonpath={.spec.members}

[knative-serving kabanero-samples]

Update the Application for Serverless

  • Edit the file app-deploy.yaml.

  • Add the line createKnativeService: true to the spec object.

apiVersion: appsody.dev/v1beta1
kind: AppsodyApplication
metadata:
  name: appsody-sample-openliberty
  namespace: kabanero-samples
spec:
  createKnativeService: true
  • Git push the change, and see tekton pipeline runs again.

  • Show the Knative resource

oc get service.serving.knative.dev/appsody-sample-smircroprofile

NAME                            URL                                                                                                                                            LATESTCREATED                         LATESTREADY                           READY     REASON
appsody-sample-smircroprofile   http://appsody-sample-smircroprofile.kabanero-samples.ocp.example.com  appsody-sample-openliberty-mtl4q   appsody-sample-openliberty-mtl4q   True
  • Show the Knative route

oc get route.serving.knative.dev/appsody-sample-smircroprofile

NAME                            URL                                                                                                                                            READY     REASON
appsody-sample-smircroprofile   http://appsody-sample-smircroprofile.kabanero-samples.ocp.example.com  True
  • Show the Knative configuration

oc get configuration.serving.knative.dev/appsody-sample-smircroprofile

NAME                            LATESTCREATED                         LATESTREADY                           READY     REASON
appsody-sample-smircroprofile   appsody-sample-openliberty-mtl4q   appsody-sample-openliberty-mtl4q   True
  • Show the Knative latest ready revision

oc get revision.serving.knative.dev/appsody-sample-openliberty-mtl4q

NAME                                  SERVICE NAME                          GENERATION   READY     REASON
appsody-sample-openliberty-mtl4q   appsody-sample-openliberty-mtl4q   2            True
oc get pods

NAME                                                              READY     STATUS    RESTARTS   AGE
appsody-sample-openliberty-mtl4q-deployment-7bf6dbddf6-rr89p   2/2       Running   0          27s
  • Wait 1 minute and you will then see the pods are not longer running

oc get pods

No resources found.