diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1012475 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.sh text eol=lf +*.yaml text eol=lf +*.yml text eol=lf \ No newline at end of file diff --git a/.github/workflows/setupOpenLibertyAks.yml b/.github/workflows/setupOpenLibertyAks.yml index f046ba7..1383baa 100644 --- a/.github/workflows/setupOpenLibertyAks.yml +++ b/.github/workflows/setupOpenLibertyAks.yml @@ -15,18 +15,20 @@ on: env: refArmttk: c11a62d4ae011ee96fdecc76d76d811c5b5a99ce refJavaee: b728442f1921282f5f3902fe5bdf7f4d2c7872ca + appInsightsName: appinsights${{ github.run_id }}${{ github.run_number }} azCliVersion: 2.40.0 azureCredentials: ${{ secrets.AZURE_CREDENTIALS }} dbName: wlsdb${{ github.run_id }}${{ github.run_number }} dbAdminUser: liberty dbPassword: ${{ secrets.DB_PASSWORD }} location: ${{ github.event.inputs.region }} + logAnalyticsName: loga${{ github.run_id }}${{ github.run_number }} namespace: default - replicas: 1 + replicas: 3 resourceGroupForDB: wlsd-db-${{ github.run_id }}-${{ github.run_number }} resourceGroupForOpenLibertyAks: ol-aks-${{ github.event.inputs.disambiguationSuffix }}-${{ github.run_number }} aksRepoUserName: WASdev - aksRepoBranchName: b37f5abcb3085ed4220287abe9f76fbda67ebe3e + aksRepoBranchName: 964f6463d6cfda9572d215cdd53109cee8f4ff1e jobs: # Make it so the bicep file that causes Liberty on AKS to be deployed is available to this workflow. @@ -202,9 +204,56 @@ jobs: --name openliberty-on-aks \ --parameters @cargotracker/src/test/aks/parameters.json \ --template-file ${artifactName}/mainTemplate.json + # Set up monitoring resources + deploy-azure-monitor: + needs: [deploy-openliberty-on-aks] + runs-on: ubuntu-20.04 + steps: + - uses: azure/login@v1 + id: azure-login + with: + creds: ${{ env.azureCredentials }} + - name: Deploy Log Analytics Workspace + id: deploy-log-analytics + uses: azure/CLI@v1 + with: + azcliversion: ${{ env.azCliVersion }} + inlineScript: | + az monitor log-analytics workspace create \ + --resource-group ${{ env.resourceGroupForOpenLibertyAks }} \ + --workspace-name ${{ env.logAnalyticsName }} \ + --location ${{ env.location }} + - name: Enable Container Insights + id: enable-container-insights + uses: azure/CLI@v1 + with: + azcliversion: ${{ env.azCliVersion }} + inlineScript: | + workspaceId=$(az monitor log-analytics workspace list -g ${{ env.resourceGroupForOpenLibertyAks }} --query '[0].id' -o tsv) + aksClusterName=$(az aks list -g ${{env.resourceGroupForOpenLibertyAks}} --query [0].name -o tsv) + + az aks enable-addons \ + --addons monitoring \ + --name ${aksClusterName} \ + --resource-group ${{ env.resourceGroupForOpenLibertyAks }} \ + --workspace-resource-id ${workspaceId} + - name: Provision Application Insights + id: provision-app-insights + uses: azure/CLI@v1 + with: + azcliversion: ${{ env.azCliVersion }} + inlineScript: | + az extension add --upgrade -n application-insights + + workspaceId=$(az monitor log-analytics workspace list -g ${{ env.resourceGroupForOpenLibertyAks }} --query '[0].id' -o tsv) + az monitor app-insights component create \ + --resource-group ${{ env.resourceGroupForOpenLibertyAks }} \ + --app ${{ env.appInsightsName }} \ + --location ${{ env.location }} \ + --workspace ${workspaceId} # Build app, push to ACR and apply it to Open Liberty servers running on AKS. deploy-cargo-tracker: - needs: [deploy-db,deploy-openliberty-on-aks] + needs: [deploy-db,deploy-azure-monitor] runs-on: ubuntu-20.04 steps: - name: Set up JDK 1.8 @@ -239,10 +288,16 @@ jobs: azureACRServer=$(az acr show -n $acrName -g ${{env.resourceGroupForOpenLibertyAks}} --query 'loginServer' -o tsv) azureACRUserName=$(az acr credential show -n $acrName -g ${{env.resourceGroupForOpenLibertyAks}} --query 'username' -o tsv) azureACRPassword=$(az acr credential show -n $acrName -g ${{env.resourceGroupForOpenLibertyAks}} --query 'passwords[0].value' -o tsv) + + az extension add --upgrade -n application-insights + appInsightsConnectionString=$(az monitor app-insights component show \ + --resource-group ${{env.resourceGroupForOpenLibertyAks}} \ + --query '[0].connectionString' -o tsv) echo "azureACRServer=${azureACRServer}" >> $GITHUB_OUTPUT echo "azureACRUserName=${azureACRUserName}" >> $GITHUB_OUTPUT echo "azureACRPassword=${azureACRPassword}" >> $GITHUB_OUTPUT + echo "appInsightsConnectionString=${appInsightsConnectionString}" >> $GITHUB_OUTPUT - name: Checkout cargotracker uses: actions/checkout@v2 with: @@ -261,6 +316,7 @@ jobs: export DB_USER=${{ env.dbAdminUser }}@${{ env.dbName }} export DB_PASSWORD=${{ env.dbPassword }} export NAMESPACE=${{ env.namespace }} + export APPLICATIONINSIGHTS_CONNECTION_STRING=${{steps.prepare_variables.outputs.appInsightsConnectionString}} mvn clean install -PopenLibertyOnAks --file cargotracker/pom.xml - name: Query version string for deployment verification run: | @@ -292,6 +348,7 @@ jobs: timestampBeforePatchingDomain=$(date +%s) cd cargotracker/target/ kubectl apply -f db-secret.yaml + kubectl apply -f app-insight.yaml kubectl apply -f openlibertyapplication.yaml # restart every time to make sure sleep 30 @@ -329,32 +386,66 @@ jobs: fi - name: Query Application URL run: | - externalIp=$(kubectl get service -o json | jq -r '.items[] | select(.metadata.name=="cargo-tracker-cluster") | .status.loadBalancer.ingress[0].ip') - echo "external ip is: " $externalIp - echo "appURL=${externalIp}:9080" >> $GITHUB_ENV - # Validate the app using playwright - - name: Verify that the app is update + gatewayPublicIPId=$(az network application-gateway list \ + --resource-group ${{env.resourceGroupForOpenLibertyAks}} \ + --query '[0].frontendIPConfigurations[0].publicIPAddress.id' -o tsv) + + gatewayUrl=$(az network public-ip show --ids ${gatewayPublicIPId} --query 'dnsSettings.fqdn' -o tsv) + + appUrl="http://${gatewayUrl}/cargo-tracker/" + + echo "appURL=${appUrl}" >> $GITHUB_ENV + # Make REST API calls to cause metrics, which will be shown in the Application Insights. + - name: Make REST API calls run: | - # install dependencies - sudo apt-get update - sudo apt-get install libegl1\ - libhyphen0\ - libopus0\ - libwoff1\ - libharfbuzz-icu0\ - libgstreamer-plugins-base1.0-0\ - libgstreamer-gl1.0-0\ - libgstreamer-plugins-bad1.0-0\ - libopenjp2-7\ - libwebpdemux2\ - libenchant1c2a\ - libgles2\ - gstreamer1.0-libav -y - appURL=http://${{ env.appURL }}/ - cd cargotracker/src/test/aks/playwright-ui-test - mvn clean install - mvn exec:java -e -Dexec.mainClass=com.microsoft.azure.javaee.FetchBuildVersion -Dexec.args="'${appURL}' '${{ env.deployVersion }}'" + # wait for application ready + attempt=0 + maxAttempt=50 + statusCode=404 + + while [[ $attempt -le ${maxAttempt} ]] && [[ "${statusCode}" != "200" ]]; do + echo "attempt: ${attempt}" + statusCode=$(curl -s -o /dev/null -w "%{http_code}" ${appURL}) + echo "http code: ${statusCode}" + attempt=$((attempt + 1)) + sleep 20 + done + + if [[ ${attempt} -gt ${maxAttempt} ]]; then + echo "Failed to access ${appURL}. " + exit 1 + fi + + # get request + curl -X GET -H "Accept: application/json" "${appURL}rest/graph-traversal/shortest-path?origin=CNHKG&destination=USNYC" + + # post request + currentDateTime=$(date +'%m/%d/%Y %I:%M %p') + cat <data.json + { + "completionTime": "${currentDateTime}", + "trackingId": "ABC123", + "eventType": "UNLOAD", + "unLocode": "USNYC", + "voyageNumber": "0200T" + } + EOF + curl -X POST -d "@data.json" -H "Content-Type: application/json" ${appURL}rest/handling/reports + + # Datetime format Failure + currentDateTime=$(date +'%m/%d/%Y %H:%M:%S') + cat <data.json + { + "completionTime": "${currentDateTime}", + "trackingId": "ABC123", + "eventType": "UNLOAD", + "unLocode": "USNYC", + "voyageNumber": "0200T" + } + EOF + curl -X POST -d "@data.json" -H "Content-Type: application/json" ${appURL}rest/handling/reports + # Print app URL to the pipeline summary page. - name: Print app URL run: | - echo "http://${appURL}" >> $GITHUB_STEP_SUMMARY \ No newline at end of file + echo "${appURL}" >> $GITHUB_STEP_SUMMARY \ No newline at end of file diff --git a/.scripts/setup-env-variables-template.sh b/.scripts/setup-env-variables-template.sh new file mode 100644 index 0000000..d229a20 --- /dev/null +++ b/.scripts/setup-env-variables-template.sh @@ -0,0 +1,9 @@ +export LIBERTY_AKS_REPO_REF="964f6463d6cfda9572d215cdd53109cee8f4ff1e" # WASdev/azure.liberty.aks +export RESOURCE_GROUP_NAME="abc1110rg" # customize this +export DB_RESOURCE_NAME="libertydb1110" # PostgreSQL server name, customize this +export DB_SERVER_NAME="${DB_RESOURCE_NAME}.postgres.database.azure.com" # PostgreSQL host name +export DB_PASSWORD="Secret123456" # PostgreSQL database password +export DB_PORT_NUMBER=5432 +export DB_NAME=postgres +export DB_USER=liberty@${DB_RESOURCE_NAME} +export NAMESPACE=default diff --git a/README.md b/README.md index d2b149f..4ba5abd 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,584 @@ -# Open Liberty Cargo Tracker Application Deployed to Azure Kubernetes Service (AKS) - -## Description - -This is a sample app template of the Domain-Driven Design Jakarta EE application. The application is built with Maven and deployed to Open Liberty running in Azure Kubernetes Service (AKS). The app template uses the [official Azure offer for running Liberty on AKS](https://aka.ms/liberty-aks). The application is exposed by Azure Load Balancer service via Public IP address. - -## Deploy Open Liberty Application to Azure Kubernetes Service: - --- -Tech stack: - -- Azure Container Registry -- Azure Kubernetes Service -- Azure PostgreSQL DB -- GitHub Actions -- Bicep -- Docker -- Maven -- Java - ---- +# Deploy Cargo Tracker to Open Liberty on Azure Kubernetes Service (AKS) + +This quickstart shows you how to deploy an existing Liberty application to AKS using Liberty on AKS solution templates. When you're finished, you can continue to manage the application via the Azure CLI or Azure Portal. + +Cargo Tracker is a Domain-Driven Design Jakarta EE application. The application is built with Maven and deployed to Open Liberty running in Azure Kubernetes Service (AKS). This [quickstart](https://learn.microsoft.com/azure/aks/howto-deploy-java-liberty-app) uses the [official Azure offer for running Liberty on AKS](https://aka.ms/liberty-aks). The application is exposed by Azure Application Gateway service. + +* [Deploy Cargo Tracker to Open Liberty on Azure Kubernetes Service (AKS)]() + * [Introduction](#introduction) + * [Prerequisites](#prerequisites) + * [Unit-1 - Deploy and monitor Cargo Tracker](#unit-1---deploy-and-monitor-cargo-tracker) + * [Clone Cargo Tracker](#clone-cargo-tracker) + * [Prepare your variables for deployments](#prepare-your-variables-for-deployments) + * [Clone Liberty on AKS Bicep templates](#clone-liberty-on-aks-bicep-templates) + * [Sign in to Azure](#sign-in-to-azure) + * [Create a resource group](#create-a-resource-group) + * [Prepare deployment parameters](#prepare-deployment-parameters) + * [Invoke Liberty on AKS Bicep template to deploy the Open Liberty Operator](#invoke-liberty-on-aks-bicep-template-to-deploy-the-open-liberty-operator) + * [Create an Azure Database for PostgreSQL instance](#create-an-azure-database-for-postgresql-instance) + * [Create Application Insights](#create-application-insights) + * [Build and deploy Cargo Tracker](#build-and-deploy-cargo-tracker) + * [Monitor Liberty application](#monitor-liberty-application) + * [Use Cargo Tracker and make a few HTTP calls](#use-cargo-tracker-and-make-a-few-http-calls) + * [Start monitoring Cargo Tracker in Application Insights](#start-monitoring-cargo-tracker-in-application-insights) + * [Start monitoring Liberty logs in Azure Log Analytics](#start-monitoring-liberty-logs-in-azure-log-analytics) + * [Start monitoring Cargo Tracker logs in Azure Log Analytics](#start-monitoring-cargo-tracker-logs-in-azure-log-analytics) + * [Unit-2 - Automate deployments using GitHub Actions](#unit-2---automate-deployments-using-github-actions) + * [Appendix 1 - Exercise Cargo Tracker Functionality](#appendix-1---exercise-cargo-tracker-functionality) + * [Appendix 2 - Learn more about Cargo Tracker](#appendix-2---learn-more-about-cargo-tracker) ## Introduction -This is a quickstart template. It deploys the following: +In this quickstart, you will: -* Deploying Cargo Tracker App: - * Create ProgresSQL Database +* Deploying Cargo Tracker: + * Create PostgreSQL Database * Create the Cargo Tracker - build with Maven - * Provisioning Azure Infra Services with ARM templates - build with BICEP + * Provisioning Azure Infra Services with BICEP templates * Create an Azure Container Registry * Create an Azure Kubernetes Service - * Build your app, Open Liberty into an image - * Push your app image to the container registry - * Deploy your app to AKS - * Expose your app with the Azure Load Balancer service - * Verify your app - -* Cargo Tracker on Automated CI/CD with GitHub Action - * CI/CD on GitHub Action - * CI/CD in action with the app - -> Refer to the [App Templates](https://github.com/microsoft/App-Templates) repo Readme for more samples that are compatible with [AzureAccelerators](https://github.com/Azure/azure-dev/). + * Build your application, Open Liberty into an image + * Push your application image to the container registry + * Deploy your application to AKS + * Expose your application with the Azure Application Gateway service + * Verify your application + * Monitor application + * Automate deployments using GitHub Actions ## Prerequisites -- Local shell with Azure CLI installed or [Azure Cloud Shell](https://ms.portal.azure.com/#cloudshell/) +- [Azure Cloud Shell](https://ms.portal.azure.com/#cloudshell/). This quickstart was tested with: + - JDK: openjdk version "11.0.18" 2023-01-17 LTS. + - GIT: git version 2.33.6. + - Kubernetes CLI version as following: + + ```bash + Client Version: version.Info{Major:"1", Minor:"26", GitVersion:"v1.26.3", GitCommit:"9e644106593f3f4aa98f8a84b23db5fa378900bd", GitTreeState:"clean", BuildDate:"2023-03-15T13:40:17Z", GoVersion:"go1.19.7", Compiler:"gc", Platform:"linux/amd64"} + Kustomize Version: v4.5.7 + ``` + - Maven: Apache Maven 3.8.7 (NON_CANONICAL). - Azure Subscription, on which you are able to create resources and assign permissions - View your subscription using ```az account show``` - If you don't have an account, you can [create one for free](https://azure.microsoft.com/free). -- GitHub CLI (optional, but strongly recommended). To install the GitHub CLI on your dev environment, see [Installation](https://cli.github.com/manual/installation). + - Your subscription is accessed using an Azure Service Principal with at least **Contributor** and **User Access Administrator** permissions. + +## Unit-1 - Deploy and monitor Cargo Tracker + +### Clone Cargo Tracker + +Clone the sample app repository to your development environment. + +```bash +mkdir cargotracker-liberty-aks +DIR="$PWD/cargotracker-liberty-aks" + +git clone https://github.com/Azure-Samples/cargotracker-liberty-aks.git ${DIR}/cargotracker +``` + +### Prepare your variables for deployments + +Create a bash script with environment variables by making a copy of the supplied template: + +```bash +cp ${DIR}/cargotracker/.scripts/setup-env-variables-template.sh ${DIR}/cargotracker/.scripts/setup-env-variables.sh +``` + +Open `${DIR}/cargotracker/.scripts/setup-env-variables.sh` and enter the following information. You can keep them with default values. + +```bash +export LIBERTY_AKS_REPO_REF="964f6463d6cfda9572d215cdd53109cee8f4ff1e" # WASdev/azure.liberty.aks +export RESOURCE_GROUP_NAME="abc1110rg" # customize this +export DB_RESOURCE_NAME="libertydb1110" # PostgreSQL server name, customize this +export DB_SERVER_NAME="${DB_RESOURCE_NAME}.postgres.database.azure.com" # PostgreSQL host name +export DB_PASSWORD="Secret123456" # PostgreSQL database password +export DB_PORT_NUMBER=5432 +export DB_NAME=postgres +export DB_USER=liberty@${DB_RESOURCE_NAME} +export NAMESPACE=default +``` + +Then, set the environment: + +```bash +source ${DIR}/cargotracker/.scripts/setup-env-variables.sh +``` + +### Clone Liberty on AKS Bicep templates + +```bash +git clone https://github.com/WASdev/azure.liberty.aks ${DIR}/azure.liberty.aks + +cd ${DIR}/azure.liberty.aks +git checkout ${LIBERTY_AKS_REPO_REF} + +cd ${DIR} +``` + +### Sign in to Azure + +If you haven't already, sign into your Azure subscription by using the `az login` command and follow the on-screen directions. + +```bash +az login +``` + +If you have multiple Azure tenants associated with your Azure credentials, you must specify which tenant you want to sign in to. You can do this with the `--tenant` option. For example, `az login --tenant contoso.onmicrosoft.com`. + +### Create a resource group + +Create a resource group with `az group create`. Resource group names must be globally unique within a subscription. + +```bash +az group create \ + --name ${RESOURCE_GROUP_NAME} \ + --location eastus +``` + +### Prepare deployment parameters + +Several parameters are required to invoke the Bicep templates. Parameters and their value are listed in the table. Make sure the variables have correct value. + +| Parameter Name | Value | Note | +|----------------|-------|------| +| `_artifactsLocation ` | `https://raw.githubusercontent.com/WASdev/azure.liberty.aks/${LIBERTY_AKS_REPO_REF}/src/main/` | This quickstart is using templates and scripts from `WASdev/azure.liberty.aks/${LIBERTY_AKS_REPO_REF}`. | +| `createCluster` | `true` | This value causes provisioning of Azure Kubernetes Service. | +| `vmSize` | `Standard_DS2_v2` | VM size of AKS node. | +| `minCount` | `1` | Minimum count of AKS nodes. | +| `maxCount` | `5` | Maximum count of AKS nodes. | +| `createACR` | `true` | This value causes provisioning of Azure Container Registry. | +| `deployApplication` | `false` | The application will be deployed on the later section. | +| `enableAppGWIngress` | `true` | The value causes to provision Azure Application Gateway Ingress Controller. | +| `appGatewayCertificateOption` | `generateCert` | The option causes generation self-signed certificate for Application Gateway. | +| `enableCookieBasedAffinity` | `true` | The value causes to enable cookie-based affinity for Application Gateway backend setting. | + +Create parameter file. + +```bash +cat <parameters.json +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "_artifactsLocation": { + "value": "https://raw.githubusercontent.com/WASdev/azure.liberty.aks/${LIBERTY_AKS_REPO_REF}/src/main/" + }, + "location": { + "value": "eastus" + }, + "createCluster": { + "value": true + }, + "vmSize": { + "value": "Standard_DS2_v2" + }, + "minCount": { + "value": 1 + }, + "maxCount": { + "value": 5 + }, + "createACR": { + "value": true + }, + "deployApplication": { + "value": false + }, + "enableAppGWIngress": { + "value": true + }, + "appGatewayCertificateOption": { + "value": "generateCert" + }, + "enableCookieBasedAffinity": { + "value": true + } + } +} +EOF +``` + +### Invoke Liberty on AKS Bicep template to deploy the Open Liberty Operator + +Invoke the Bicep template in ${DIR}/azure.liberty.aks/src/main/bicep/mainTemplate.bicep to deploy Open Liberty Operator on AKS. + +Run the following command to validate the parameter file. + +```bash +az deployment group validate \ + --resource-group ${RESOURCE_GROUP_NAME} \ + --name liberty-on-aks \ + --parameters @parameters.json \ + --template-file ${DIR}/azure.liberty.aks/src/main/bicep/mainTemplate.bicep +``` + +The command should be completed without error. If there is, you must resolve it before moving on. + +Next, invoke the template. + +```bash +az deployment group create \ + --resource-group ${RESOURCE_GROUP_NAME} \ + --name liberty-on-aks \ + --parameters @parameters.json \ + --template-file ${DIR}/azure.liberty.aks/src/main/bicep/mainTemplate.bicep +``` + +It takes more than 10 minutes to finish the deployment. The Open Liberty Operator is running in namespace `default`. + +If you are using Azure Cloud Shell, the terminal may have been disconnected, run source /cargotracker/.scripts/setup-env-variables.sh to set the variables. + +### Create an Azure Database for PostgreSQL instance + +Use `az postgres server create` to provision a PostgreSQL instance on Azure. The data server allows access from Azure Services. + +```bash +az postgres server create \ + --resource-group ${RESOURCE_GROUP_NAME} \ + --name ${DB_RESOURCE_NAME} \ + --location eastus \ + --admin-user liberty \ + --ssl-enforcement Disabled \ + --public-network-access Enabled \ + --admin-password ${DB_PASSWORD} \ + --sku-name B_Gen5_1 + + echo "Allow Access To Azure Services" + az postgres server firewall-rule create \ + -g ${RESOURCE_GROUP_NAME} \ + -s ${DB_RESOURCE_NAME} \ + -n "AllowAllWindowsAzureIps" \ + --start-ip-address "0.0.0.0" \ + --end-ip-address "0.0.0.0" +``` + +### Create Application Insights + +To integrate with Application Insights, you need to have an Application Insights instance and expose metrics to it using the Java agent. + +First, install or upgrade `application-insights` extension. + +```bash +az extension add --upgrade -n application-insights +``` + +Create a Log Analytics Workspace. + +```bash +WORKSPACE_NAME="loga$(date +%s)" +az monitor log-analytics workspace create \ + --resource-group ${RESOURCE_GROUP_NAME} \ + --workspace-name ${WORKSPACE_NAME} \ + --location eastus + +WORKSPACE_ID=$(az monitor log-analytics workspace list -g ${RESOURCE_GROUP_NAME} --query '[0].id' -o tsv) +``` + + +This quickstart uses Container Insights to monitor AKS. Enable it with the following commands. + +```bash +AKS_NAME=$(az aks list -g ${RESOURCE_GROUP_NAME} --query [0].name -o tsv) + +az aks enable-addons \ + --addons monitoring \ + --name ${AKS_NAME} \ + --resource-group ${RESOURCE_GROUP_NAME} \ + --workspace-resource-id ${WORKSPACE_ID} +``` + +Next, provision Application Insights. + +```bash +APPINSIGHTS_NAME="appinsights$(date +%s)" +az monitor app-insights component create \ + --resource-group ${RESOURCE_GROUP_NAME} \ + --app ${APPINSIGHTS_NAME} \ + --location eastus \ + --workspace ${WORKSPACE_ID} +``` + +Obtain the connection string of Application Insights which will be used in later section. + +```bash +export APPLICATIONINSIGHTS_CONNECTION_STRING=$(az monitor app-insights component show \ + --resource-group ${RESOURCE_GROUP_NAME} \ + --query '[0].connectionString' -o tsv) +``` + +### Build and deploy Cargo Tracker + +First, prepare the environment variables used in the build time. If you haven't set the deployment variables, run the following command: + +```bash +source ${DIR}/cargotracker/.scripts/setup-env-variables.sh +``` + +Next, obtain the registry information. + +```bash +export REGISTRY_NAME=$(az acr list -g ${RESOURCE_GROUP_NAME} --query '[0].name' -o tsv) +export LOGIN_SERVER=$(az acr show -n ${REGISTRY_NAME} -g ${RESOURCE_GROUP_NAME} --query 'loginServer' -o tsv) +``` + +Now, it's ready to build Cargo Tracker. + +```bash +mvn clean install -PopenLibertyOnAks --file ${DIR}/cargotracker/pom.xml +``` + +The war file locates in `${DIR}/cargotracker/target/cargo-tracker.war`. + +The following steps are to build a container image which will be deployed to AKS. + +The image tag is constructed with `${project.artifactId}:${project.version}`. Run the following command to obtain their values. + +```bash +IMAGE_NAME=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.artifactId}' --non-recursive exec:exec --file ${DIR}/cargotracker/pom.xml) +IMAGE_VERSION=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec --file ${DIR}/cargotracker/pom.xml) +``` + +Run `ac acr built` command to build the container image. + +```bash +cd ${DIR}/cargotracker/target +az acr build -t ${IMAGE_NAME}:${IMAGE_VERSION} -r ${REGISTRY_NAME} . +``` + +The image is ready to deploy to AKS. Run the following command to connect to AKS cluster. + +```bash +AKS_NAME=$(az aks list -g ${RESOURCE_GROUP_NAME} --query [0].name -o tsv) + +az aks get-credentials --resource-group ${RESOURCE_GROUP_NAME} --name $AKS_NAME +``` + +Run the following command to create secrets for data source connection and Application Insights connection. + +Then deploy the container image to AKS cluster. + +```bash +kubectl apply -f ${DIR}/cargotracker/target/db-secret.yaml +kubectl apply -f ${DIR}/cargotracker/target/app-insight.yaml +kubectl apply -f ${DIR}/cargotracker/target/openlibertyapplication.yaml + +kubectl get pod -w +``` + +Press `Control + C` to exit the watching mode. + +Now, Cargo Tracker is running on Open Liberty, and connecting to Application Insights. You are able to monitor the application. + +### Monitor Liberty application + +This section uses Application Insights and Azure Log Analytics to monitor Open Liberty and Cargo Tracker. You can find the resource from your working resource group. + +#### Use Cargo Tracker and make a few HTTP calls + +You can open Cargo Tracker in your web browser and follow [Appendix 1 - Exercise Cargo Tracker Functionality](#appendix-1---exercise-cargo-tracker-functionality) to make some calls. + +Use the following commands to obtain URL of Cargo Tracker. When accessing the application, if you get "502 Bad Gateway" response, just wait a few minutes. + + +```bash +GATEWAY_PUBLICIP_ID=$(az network application-gateway list \ + --resource-group ${RESOURCE_GROUP_NAME} \ + --query '[0].frontendIPConfigurations[0].publicIPAddress.id' -o tsv) + +GATEWAY_URL=$(az network public-ip show --ids ${GATEWAY_PUBLICIP_ID} --query 'dnsSettings.fqdn' -o tsv) + +CARGO_TRACKER_URL="http://${GATEWAY_URL}/cargo-tracker/" + +echo "Cargo Tracker URL: ${CARGO_TRACKER_URL}" +``` + +You can also `curl` the REST API exposed by Cargo Tracker. It's strongly recommended you get familiar with Cargo Tracker with the above exercise. +The `/graph-traversal/shortest-path` REST API allows you to retrieve shortest path from origin to destination. -## Getting Started +The API requires the following parameters: + +| Parameter Name | Value | +| ------------------| ----------------- | +| `origin` | The UN location code value of origin and destination must be five characters long, the first two must be alphabetic and the last three must be alphanumeric (excluding 0 and 1). | +| `destination` | The UN location code value of origin and destination must be five characters long, the first two must be alphabetic and the last three must be alphanumeric (excluding 0 and 1). | +| `deadline` | **Optional**. Deadline value must be eight characters long. | + +You can run the following curl command: + +```bash +curl -X GET -H "Accept: application/json" "${CARGO_TRACKER_URL}rest/graph-traversal/shortest-path?origin=CNHKG&destination=USNYC" +``` + +The `/handling/reports` REST API allows you to send an asynchronous message with the information to the handling event registration system for proper registration. + +The API requires the following parameters: + +| Parameter Name | Value | +| ------------------| ----------------- | +| `completionTime` | Must be ClockHourOfAmPm. Format: `m/d/yyyy HH:MM tt`, e.g `3/29/2023 9:30 AM` | +| `trackingId` | Tracking ID must be at least four characters. | +| `eventType` | Event type value must be one of: RECEIVE, LOAD, UNLOAD, CUSTOMS, CLAIM. | +| `unLocode` | The UN location code value of origin and destination must be five characters long, the first two must be alphabetic and the last three must be alphanumeric (excluding 0 and 1). | +| `voyageNumber` | **Optional**. Voyage number value must be between four and five characters long. | + +You can run the following `curl` command to load onto voyage 0200T in New York for trackingId of `ABC123`: + +```bash +DATE=$(date +'%m/%d/%Y %I:%M %p') +cat <data.json +{ + "completionTime": "${DATE}", + "trackingId": "ABC123", + "eventType": "UNLOAD", + "unLocode": "USNYC", + "voyageNumber": "0200T" +} +EOF + +curl -X POST -d "@data.json" -H "Content-Type: application/json" ${CARGO_TRACKER_URL}rest/handling/reports +``` + +You can use Application Insights to detect failures. Run the following `curl` command to cause a failed call. The REST API fails at incorrect datetime format. + +```bash +DATE=$(date +'%m/%d/%Y %H:%M:%S') +cat <data.json +{ + "completionTime": "${DATE}", + "trackingId": "ABC123", + "eventType": "UNLOAD", + "unLocode": "USNYC", + "voyageNumber": "0200T" +} +EOF + +curl -X POST -d "@data.json" -H "Content-Type: application/json" ${CARGO_TRACKER_URL}rest/handling/reports +``` + +#### Start monitoring Cargo Tracker in Application Insights + +Open the Application Insights and start monitoring Cargo Tracker. You can find the Application Insights in the same Resource Group where you created deployments using Bicep templates. + +Navigate to the `Application Map` blade: + +![Cargo Tracker Application Map in Application Insights](media/app-insights-app-map.png) + +Navigate to the `Performance` blade: + +![Cargo Tracker Performance in Application Insights](media/app-insights-performance.png) + +Select operation **GET /cargo-tracker/cargo**, select **Drill into...**, **number-N Samples** you will find the operations are listed in the right panel. + +Select the first operation with response code 200, the **End-to-end transaction details** page shows. + +![Cargo Tracker transaction details in Application Insights](media/app-insights-cargo-end-to-end-transaction.png) + +Select operation **POST /cargo-tracker/rest/handling/reports**, select **Drill into...**, **number-N Samples** you will find the operations are listed in the right panel. + +Select the first operation with response code 204. Select the **View all** button in **Traces & events** panel, the traces and events are listed. + +![Cargo Tracker traces and events in Application Insights](media/app-insights-cargo-reports-traces.png) + +Navigate to the `Failures/Exceptions` blade - you can see a collection of exceptions: + +![Cargo Tracker Failures in Application Insights](media/app-insights-failures.png) + +Click on an exception to see the end-to-end transaction and stack trace in context: + +![Cargo Tracker stacktrace in Application Insights](media/app-insights-failure-details.png) + +Navigate to the Live Metrics blade - you can see live metrics on screen with low latencies < 1 second: + +![Cargo Tracker Live Metrics in Application Insights](media/app-insights-live-metrics.png) + +#### Start monitoring Liberty logs in Azure Log Analytics + +Open the Log Analytics that created in previous steps. + +In the Log Analytics page, select `Logs` blade and run any of the sample queries supplied below for Open Liberty server logs. + +Make sure the quary scope is your aks instance. + +First, get the pod name of each server. + +```bash +kubectl get pod +``` + +You will get output like the following content. The first three pods are running Open Liberty servers. The last one is running Open Liberty Operator. + +```bash +NAME READY STATUS RESTARTS AGE +cargo-tracker-cluster-7c6df94fc7-5rpjd 1/1 Running 0 2m50s +cargo-tracker-cluster-7c6df94fc7-hrvln 1/1 Running 0 2m50s +cargo-tracker-cluster-7c6df94fc7-pr6zj 1/1 Running 0 2m50s +olo-controller-manager-77cc59655b-2r5qg 1/1 Running 0 2d5h +``` + +Type and run the following Kusto query to see operator logs, replace the `ContainerHostname` with the operator pod name displayed above. + +```sql +ContainerInventory +| where ContainerHostname == 'olo-controller-manager-77cc59655b-2r5qg' +| project ContainerID +| take 1 +| join (ContainerLog + | project ContainerID, LogEntry, TimeGenerated) + on ContainerID +| sort by TimeGenerated +| limit 500 +| project LogEntry +``` + +Type and run the following Kusto query to see Open Liberty server logs, replace the `ContainerHostname` with one of Open Liberty server name displayed above. + +```bash +ContainerInventory +| where ContainerHostname == 'cargo-tracker-cluster-7c6df94fc7-5rpjd' +| project ContainerID +| take 1 +| join (ContainerLog + | project ContainerID, LogEntry, TimeGenerated) + on ContainerID +| sort by TimeGenerated +| limit 500 +| project LogEntry +``` + +You can change the server pod name to query expected server logs. + +#### Start monitoring Cargo Tracker logs in Azure Log Analytics + +Open the Log Analytics that created in previous steps. + +In the Log Analytics page, select `Logs` blade and run any of the sample queries supplied below for Application logs. + +Type and run the following Kusto query to obtain failed dependencies: + +```sql +AppDependencies +| where Success == false +| project Target, DependencyType, Name, Data, OperationId, AppRoleInstance +``` + +Type and run the following Kusto query to obtain `java.time.format.DateTimeParseException` exceptions: + +```sql +AppExceptions +| where ExceptionType == "java.time.format.DateTimeParseException" +| project TimeGenerated, ProblemId, Method, OuterMessage, AppRoleInstance +| sort by TimeGenerated +| limit 100 +``` + +Type and run the following Kusto query to obtain specified failed request: + +```sql +AppRequests +| where OperationName == "POST /cargo-tracker/rest/handling/reports" and ResultCode == "500" +``` + +## Unit-2 - Automate deployments using GitHub Actions 1. Fork the repository by clicking the 'Fork' button on the top right of the page. This creates a local copy of the repository for you to work in. @@ -69,11 +596,11 @@ This creates a local copy of the repository for you to work in. 5. Click Run workflow. -## Workflow description +### Workflow description As mentioned above, the app template uses the [official Azure offer for running Liberty on AKS](https://aka.ms/liberty-aks). The workflow uses the source code behind that offer by checking it out and invoking it from Azure CLI. -### Job: preflight +#### Job: preflight This job is to build Liberty on AKS template into a ZIP file containing the ARM template to invoke. @@ -95,16 +622,16 @@ This job is to build Liberty on AKS template into a ZIP file containing the ARM + Archive Archive azure.liberty.aks template template. Upload the ZIP file to the pipeline. The later jobs will download the ZIP file for further deployments. -### Job: deploy-db +#### Job: deploy-db -This job is to deploy PostgreSQL server and configure firewall setting. +This job is to deploy PostgreSQL server and configure firewall settings. * Set Up Azure Database for PostgreSQL + azure-login. Login Azure. + Create Resource Group. Create a resource group to which the database will deploy. + Set Up Azure Postgresql to Test dbTemplate. Provision Azure Database for PostgreSQL Single Server. The server allows access from Azure services. -### Job: deploy-openliberty-on-aks +#### Job: deploy-openliberty-on-aks This job is to provision Azure resources, run Open Liberty Operator on AKS using the solution template. @@ -119,12 +646,18 @@ This job is to provision Azure resources, run Open Liberty Operator on AKS using + Create Resource Group. Create a resource group for Liberty on AKS. + Checkout cargotracker. Checkout the parameter template. + Prepare parameter file. Set values to the parameters. - + Validate Deploy of Open Liberty Server Cluster Domain offer. Validate the parameters file in the context of the bicep template to be invoked. This will catch some errors before taking the time to start the full deployment. `--template-file` is the mainTemplate.json from solution template ZIP file. `--parameters` is the parameter file created in last step. + + Validate Deploy of Open Liberty Server Cluster Domain offer. Validate the parameters file in the context of the bicep template to be invoked. This will catch some errors before taking the time to start the full deployment. `--template-file` is the mainTemplate.json from solution template ZIP file. `--parameters` is the parameter file created in the last step. + Deploy Open Liberty Server Cluster Domain offer. Invoke the mainTemplate.json to deploy resources and configurations. After the deployment completes, you'll get the following result: + An Azure Container Registry. It'll store app image in the later steps. + An Azure Kubernetes Service with Open Liberty Operator running in `default` namespace. -### Job: deploy-cargo-tracke +#### Job: deploy-azure-monitor + + azure-login. Login Azure. + + Deploy Log Analytics Workspace. Provision Log Analytics Workspace to store logs for Container Insights and metrics for Application Insights. + + Enable Container Insights. Enable Azure Monitor in the existing AKS cluster and enable Container Insights. + + Provision Application Insights. Provision Application Insights to monitor the application. Cargo Tracker will connect to the App Insight in later steps. Application Insights shares the same workspace with Container Insights. + +#### Job: deploy-cargo-tracker This job is to build app, push it to ACR and apply it to Open Liberty server running on AKS. @@ -135,27 +668,22 @@ This job is to build app, push it to ACR and apply it to Open Liberty server run * Deploy Cargo Tracker + Checkout cargotracker. Checkout source code of cargo tracker from this repository. - + Build the app. Set required environment variables and build cargo tracker with Maven. + + Build the applications. Set required environment variables and build cargo tracker with Maven. + Query version string for deployment verification. Obtain the app version string for later verification. - + Build image and upload to ACR. Build cargo tracker into a docker image with docker file locating in [Dockerfile](Dockerfile), and push the image to ACR. + + Build an image and upload to ACR. Build cargo tracker into a docker image with docker file locating in [Dockerfile](Dockerfile), and push the image to ACR. + Connect to AKS cluster. Connect to AKS cluster to deploy cargo tracker. - + Apply deployment files. Apply data source configuration in `target/db-secret.yaml` and cargo tracker metadata in `target/openlibertyapplication.yaml`. This will cause cargo tracker deployed to the AKS cluster. - + Verify pods are ready. Make sure cargo tracker is live. + + Apply deployment files. Apply data source configuration in `target/db-secret.yaml`, App Insight configuration in `target/app-insight.yaml` and cargo tracker metadata in `target/openlibertyapplication.yaml`. This will cause cargo tracker deployed to the AKS cluster. + + Verify pods are ready. Make sure Cargo Tracker is live. + Query Application URL. Obtain cargo tracker URL. - + Verify that the app is update. Make sure cargo tracker is running by validating its version string. - + Print app URL. Print the cargo tracker URL to pipeline summary page. Now you'are able to access cargo tracker with the URL from your browser. - -## Cargo Tracker Website - -![Cargo Tracker Website](cargo_tracker_website.png) -If you wish to view the Cargo Tracker Deployment, you have the following options: +* Make REST API calls + + A HTTP GET request. + + A HTTP POST request. + + An datetime format failure request. -- Open the pipeline "Setup OpenLiberty on AKS". You will find the **Summary** page. -- Scroll down to **deploy-cargo-tracker summary**, you'll find the app URL. -- Open your web browser, navigate to the application URL, you will see the Cargo Tracker landing page. +* Print app URL. Print the cargo tracker URL to pipeline summary page. Now you'are able to access cargo tracker with the URL from your browser. -## Exercise Cargo Tracker Functionality +## Appendix 1 - Exercise Cargo Tracker Functionality 1. On the main page, select **Public Tracking Interface** in new window. @@ -163,7 +691,7 @@ If you wish to view the Cargo Tracker Deployment, you have the following options 1. Observe what the **next expected activity** is. -1. On the main page, select **Administration Interface**, then, in the left navigation column select **Live** in a new window. This opens up a map view. +1. On the main page, select **Administration Interface**, then, in the left navigation column select **Live** in a new window. This opens a map view. 1. Mouse over the pins and find the one for **ABC123**. Take note of the information in the hover window. @@ -181,10 +709,10 @@ If you wish to view the Cargo Tracker Deployment, you have the following options 1. Review the information and verify it matches the **next expected activity**. If not, go back and fix it. If so, select **Submit**. -1. Back on the **Public Tracking Interface** select **Tracking** then enter **ABC123** and select **Track**. Observe that a different. **next expected activity** is listed. +1. Back on the **Public Tracking Interface** select **Tracking** then enter **ABC123** and select **Track**. Observe that different. **next expected activity** is listed. 1. If desired, go back to **Mobile Event Logger** and continue performing the next activity. -## Learn more about Cargo Tracker +## Appendix 2 - Learn more about Cargo Tracker -See [Eclipse Cargo Tracker - Applied Domain-Driven Design Blueprints for Jakarta EE](cargo-tracker.md) \ No newline at end of file +See [Eclipse Cargo Tracker - Applied Domain-Driven Design Blueprints for Jakarta EE](https://github.com/eclipse-ee4j/cargotracker/) \ No newline at end of file diff --git a/cargo-tracker.md b/cargo-tracker.md deleted file mode 100644 index c2f75c6..0000000 --- a/cargo-tracker.md +++ /dev/null @@ -1,139 +0,0 @@ -# Eclipse Cargo Tracker - Applied Domain-Driven Design Blueprints for Jakarta EE - -The project demonstrates how you can develop applications with Jakarta EE using widely adopted architectural best practices like Domain-Driven -Design (DDD). The project is directly based on the well known -original [Java DDD sample application](http://dddsample.sourceforge.net) -developed by DDD pioneer Eric Evans' company Domain Language and the Swedish -software consulting company Citerus. The cargo example actually comes from -Eric Evans' seminal book on DDD. The original application is written in Spring, -Hibernate and Jetty whereas the application is built on Jakarta EE. - -The application is an end-to-end system for keeping track of shipping cargo. It -has several interfaces described in the following sections. - -For further details on the project, please visit: https://eclipse-ee4j.github.io/cargotracker/. - -A slide deck introducing the -fundamentals of the project is available on the official Eclipse -Foundation [Jakarta EE SlideShare account](https://www.slideshare.net/Jakarta_EE/applied-domaindriven-design-blueprints-for-jakarta-ee). - -![Cargo Tracker cover](cargo_tracker_cover.png) - -## Getting Started - -The [project website](https://eclipse-ee4j.github.io/cargotracker/) has detailed information on how to get started. - -The simplest steps are the following (no IDE required): - -* Get the project source code. -* Ensure you are running Java SE 8 or Java SE 11. -* Make sure JAVA_HOME is set. -* As long as you have Maven set up properly, navigate to the project source root and - type: `mvn clean package cargo:run` -* Go to http://localhost:8080/cargo-tracker - -To set up in Eclipse, follow these steps: - -* Set up Java SE 8 or Java SE 11, [Eclipse for Enterprise Java Developers](https://www.eclipse.org/downloads/packages/) and [Payara 5](https://www.payara.fish/downloads/). You will also need to set up [Payara Tools](https://marketplace.eclipse.org/content/payara-tools) in Eclipse. -* Import this code in Eclipse as a Maven project, - Eclipse will do the rest for you. Proceed with clean/building the application. -* After the project is built (which will take a while the very first time as Maven downloads dependencies), simply run it via Payara 5. - -## Exploring the Application - -After the application runs, it will be available at: -http://localhost:8080/cargo-tracker/. Under the hood, the application uses a -number of Jakarta EE features including Faces, CDI, Enterprise Beans, Persistence, REST, Batch, JSON Binding, Bean Validation and Messaging. - -There are several web interfaces, REST interfaces and a file system scanning -interface. It's probably best to start exploring the interfaces in the rough -order below. - -The tracking interface let's you track the status of cargo and is -intended for the general public. Try entering a tracking ID like ABC123 (the -application is pre-populated with some sample data). - -The administrative interface is intended for the shipping company that manages -cargo. The landing page of the interface is a dashboard providing an overall -view of registered cargo. You can book cargo using the booking interface. -One cargo is booked, you can route it. When you initiate a routing request, -the system will determine routes that might work for the cargo. Once you select -a route, the cargo will be ready to process handling events at the port. You can -also change the destination for cargo if needed or track cargo. - -The Handling Event Logging interface is intended for port personnel registering what -happened to cargo. The interface is primarily intended for mobile devices, but -you can use it via a desktop browser. The interface is accessible at this URL: http://localhost:8080/cargo-tracker/event-logger/index.xhtml. For convenience, you -could use a mobile emulator instead of an actual mobile device. Generally speaking cargo -goes through these events: - -* It's received at the origin location. -* It's loaded and unloaded onto voyages on it's itinerary. -* It's claimed at it's destination location. -* It may go through customs at arbitrary points. - -While filling out the event registration form, it's best to have the itinerary -handy. You can access the itinerary for registered cargo via the admin interface. The cargo handling is done via Messaging for scalability. While using the event logger, note that only the load and unload events require as associated voyage. - -You should also explore the file system based bulk event registration interface. -It reads files under /tmp/uploads. The files are just CSV files. A sample CSV -file is available under [src/test/sample/handling_events.csv](src/test/sample/handling_events.csv). The sample is already set up to match the remaining itinerary events for cargo ABC123. Just make sure to update the times in the first column of the sample CSV file to match the itinerary as well. - -Sucessfully processed entries are archived under /tmp/archive. Any failed records are -archived under /tmp/failed. - -Don't worry about making mistakes. The application is intended to be fairly -error tolerant. If you do come across issues, you should [report them](https://github.com/eclipse-ee4j/cargotracker/issues). - -You can simply remove ./cargo-tracker-database from the file system to restart fresh. This directory will typically be under $your-payara-installation/glassfish/domains/domain1/config. - -You can also use the soapUI scripts included in the source code to explore the -REST interfaces as well as the numerous unit tests covering the code base -generally. Some of the tests use Arquillian. - -## Exploring the Code - -As mentioned earlier, the real point of the application is demonstrating how to -create well architected, effective Jakarta EE applications. To that end, once you -have gotten some familiarity with the application functionality the next thing -to do is to dig right into the code. - -DDD is a key aspect of the architecture, so it's important to get at least a -working understanding of DDD. As the name implies, Domain-Driven Design is an -approach to software design and development that focuses on the core domain and -domain logic. - -For the most part, it's fine if you are new to Jakarta EE. As long as you have a -basic understanding of server-side applications, the code should be good enough to get started. For learning Jakarta EE further, -we have recommended a few links in the resources section of the project site. Of -course, the ideal user of the project is someone who has a basic working -understanding both Jakarta EE and DDD. Though it's not our goal to become a kitchen -sink example for demonstrating the vast amount of APIs and features in Jakarta EE, -we do use a very representative set. You'll find that you'll learn a fair amount -by simply digging into the code to see how things are implemented. - -## Java EE 7 -A Java EE 7, Java SE 8, Payara 4.1 version of Cargo Tracker is available under the ['javaee7' branch](https://github.com/eclipse-ee4j/cargotracker/tree/javaee7). - -## Contributing -This project complies with the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html). You can use the [google-java-format](https://github.com/google/google-java-format) tool to help you comply with the Google Java Style Guide. You can use the tool with most major IDEs such as Eclipse and IntelliJ. - -In addition, for all XML, XHTML and HTML files we use a column/line width of 100 and we use 4 spaces for indentation. Please adjust the formatting settings of your IDE accordingly. - -For further guidance on contributing including the project roadmap, please look [here](CONTRIBUTING.md). - -## Known Issues -* When you load the project in the Eclipse IDE, you may get some spurious validation failure messages on the pom.xml file. These are harmless and the Maven build is just - fine. You can simply ignore these false validation messages or delete them by going to Markers -> XML Problem. -* When you load the project in the Eclipse IDE, you may get some spurious validation failure messages on the web.xml file. These are harmless and the war configuration is - just fine. You can simply ignore these false validation messages or delete them by going to Markers -> XML Problem and Markers -> Language Servers. -* You may get a log message stating that Payara SSL certificates have expired. This won't get in the way of functionality, but it will - stop log messages from being printed to the IDE console. You can solve this issue by manually removing the expired certificates from the Payara domain, as - explained [here](https://github.com/payara/Payara/issues/3038). -* If you restart the application a few times, you will run into a bug causing a spurious deployment failure. While the problem can be annoying, it's harmless. - Just re-run the application (make sure to completely un-deploy the application and shut down Payara first). -* Sometimes when the server is not shut down correctly or there is a locking/permissions issue, the H2 database that - the application uses get's corrupted, resulting in strange database errors. If - this occurs, you will need to stop the application and clean the database. You - can do this by simply removing ./cargo-tracker-database from the file - system and restarting the application. This directory will typically be under $your-payara-installation/glassfish/domains/domain1/config. diff --git a/cargo_tracker_cover.png b/cargo_tracker_cover.png deleted file mode 100644 index 968f735..0000000 Binary files a/cargo_tracker_cover.png and /dev/null differ diff --git a/cargo_tracker_website.png b/cargo_tracker_website.png deleted file mode 100644 index 1dbe416..0000000 Binary files a/cargo_tracker_website.png and /dev/null differ diff --git a/env.md b/env.md index 3bb6b51..6c4ac0c 100644 --- a/env.md +++ b/env.md @@ -62,6 +62,7 @@ export DB_NAME=postgres export DB_USER=ejb010212d@ejb010212d export DB_PASSWORD='Secret123!' export NAMESPACE=default +export APPLICATIONINSIGHTS_CONNECTION_STRING='InstrumentationKey=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx;IngestionEndpoint=https://eastus-6.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/' echo REGISTRY_NAME=${REGISTRY_NAME} echo LOGIN_SERVER=${LOGIN_SERVER} diff --git a/media/app-insights-app-map.png b/media/app-insights-app-map.png new file mode 100644 index 0000000..8054635 Binary files /dev/null and b/media/app-insights-app-map.png differ diff --git a/media/app-insights-cargo-end-to-end-transaction.png b/media/app-insights-cargo-end-to-end-transaction.png new file mode 100644 index 0000000..d0857be Binary files /dev/null and b/media/app-insights-cargo-end-to-end-transaction.png differ diff --git a/media/app-insights-cargo-reports-traces.png b/media/app-insights-cargo-reports-traces.png new file mode 100644 index 0000000..320ac0e Binary files /dev/null and b/media/app-insights-cargo-reports-traces.png differ diff --git a/media/app-insights-failure-details.png b/media/app-insights-failure-details.png new file mode 100644 index 0000000..9d6684a Binary files /dev/null and b/media/app-insights-failure-details.png differ diff --git a/media/app-insights-failures.png b/media/app-insights-failures.png new file mode 100644 index 0000000..0da1297 Binary files /dev/null and b/media/app-insights-failures.png differ diff --git a/media/app-insights-live-metrics.png b/media/app-insights-live-metrics.png new file mode 100644 index 0000000..86355f4 Binary files /dev/null and b/media/app-insights-live-metrics.png differ diff --git a/media/app-insights-performance.png b/media/app-insights-performance.png new file mode 100644 index 0000000..7bccb56 Binary files /dev/null and b/media/app-insights-performance.png differ diff --git a/pom.xml b/pom.xml index 8063586..24ad18d 100644 --- a/pom.xml +++ b/pom.xml @@ -178,153 +178,6 @@ - - - - weblogicOnVm - - false - - - http://localhost:8001/cargo-tracker/rest/graph-traversal/shortest-path - org.apache.derby.jdbc.EmbeddedDriver - jdbc:derby:${webapp.databaseTempDir}/cargo-tracker-database;create=true - jdbc/CargoTrackerDB - postgresql-initital-data.sql - ${maven.build.timestamp} - yyyy-MM-dd HH:mm:ss - - - - - org.glassfish.jersey.containers - jersey-container-servlet-core - 2.0 - provided - - - - org.jboss.arquillian.container - arquillian-wls-remote-12.1.2 - 1.0.0.Alpha3 - test - - - - - - src/main/resources - true - - - - - src/test/resources - true - - - - - org.apache.maven.plugins - maven-war-plugin - 2.6 - - false - true - ${basedir}/src/main/webapp/WEB-INF/web.xml - - - - maven-surefire-plugin - 2.18.1 - - true - - - ${project.activeProfiles[0].id} - - ${project.activeProfiles[0].id} - - - - - - - - - weblogicOnAks - - false - - - http://sample-domain1-cluster-cluster-1:8001/cargo-tracker/rest/graph-traversal/shortest-path - org.apache.derby.jdbc.EmbeddedDriver - jdbc:derby:${webapp.databaseTempDir}/cargo-tracker-database;create=true - jdbc/CargoTrackerDB - postgresql-initital-data.sql - ${maven.build.timestamp} - yyyy-MM-dd HH:mm:ss - - - - - org.glassfish.jersey.containers - jersey-container-servlet-core - 2.0 - provided - - - - org.jboss.arquillian.container - arquillian-wls-remote-12.1.2 - 1.0.0.Alpha3 - test - - - - - - src/main/resources - true - - - - - src/test/resources - true - - - - - org.apache.maven.plugins - maven-war-plugin - 2.6 - - false - true - ${basedir}/src/main/webapp/WEB-INF/web.xml - - - - maven-surefire-plugin - 2.18.1 - - true - - - ${project.activeProfiles[0].id} - - ${project.activeProfiles[0].id} - - - - - - openLibertyOnAks @@ -337,22 +190,15 @@ postgresql-initital-data.sql ${maven.build.timestamp} yyyy-MM-dd HH:mm:ss - ${db.server.name} - ${db.port.number} - ${db.name} - ${db.user} - ${db.password} ${env.LOGIN_SERVER} - ${env.REGISTRY_NAME} - ${env.PASSWORD} - ${env.USER_NAME} ${env.DB_SERVER_NAME} ${env.DB_PORT_NUMBER} ${env.DB_NAME} ${env.DB_USER} ${env.DB_PASSWORD} ${env.NAMESPACE} - 1 + 3 + ${env.APPLICATIONINSIGHTS_CONNECTION_STRING} @@ -372,12 +218,6 @@ jersey-media-sse 3.0.3 - - org.postgresql - postgresql - 42.2.4 - jar - @@ -396,7 +236,7 @@ org.apache.maven.plugins maven-war-plugin - 2.6 + 3.3.2 false true @@ -405,7 +245,7 @@ maven-surefire-plugin - 2.18.1 + 2.22.2 true @@ -424,22 +264,38 @@ 3.1.2 - copy-jdbc-driver + copy package - copy-dependencies + copy - - postgresql - ${project.build.directory}/liberty/wlp/usr/shared/resources - + + + + org.postgresql + postgresql + 42.3.8 + jar + ${project.build.directory}/liberty/wlp/usr/shared/resources + postgresql.jar + + + com.microsoft.azure + applicationinsights-agent + 3.4.11 + jar + src/main/liberty/config + applicationinsights-agent.jar + + + io.openliberty.tools liberty-maven-plugin - 3.5.1 + 3.6.1 package-server @@ -497,199 +353,6 @@ - - payara - - true - - - 5.2021.2 - - http://localhost:8080/cargo-tracker/rest/graph-traversal/shortest-path - org.h2.jdbcx.JdbcDataSource - - jdbc:h2:file:./cargo-tracker-data/cargo-tracker-database;create=true - - - - - - org.glassfish.jersey.core - jersey-server - 2.33 - provided - - - - - com.h2database - h2 - 1.4.200 - runtime - - - fish.payara.arquillian - arquillian-payara-micro-managed - 2.4.1 - test - - - - - - src/main/resources - true - - - - - src/test/resources - true - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.1.2 - - - copy - process-test-resources - - copy - - - - - - - fish.payara.extras - payara-micro - ${payara.version} - false - ${project.build.directory} - payara-micro.jar - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.22.2 - - - ${project.build.directory}/payara-micro.jar - - - - - org.codehaus.cargo - cargo-maven2-plugin - 1.8.5 - - - payara - - fish.payara.distributions - payara - ${payara.version} - - - - - - - - - - - cloud - - false - - - 5.2021.2 - http://localhost:8080/rest/graph-traversal/shortest-path - org.postgresql.ds.PGPoolingDataSource - - ${postgreSqlJdbcUrl} - - - - - - org.glassfish.jersey.core - jersey-server - 2.33 - provided - - - - - com.h2database - h2 - 1.4.200 - test - - - fish.payara.arquillian - arquillian-payara-micro-managed - 2.4.1 - test - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.1.2 - - - copy - process-test-resources - - copy - - - - - - - fish.payara.extras - payara-micro - ${payara.version} - false - ${project.build.directory} - payara-micro.jar - - - org.postgresql - postgresql - 42.2.20 - false - ${project.build.directory} - postgresql.jar - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.22.2 - - - ${project.build.directory}/payara-micro.jar - - - - - - server-xml diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEvent.java b/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEvent.java index 17a0685..f69725c 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEvent.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/handling/HandlingEvent.java @@ -48,7 +48,6 @@ public class HandlingEvent implements Serializable { private static final long serialVersionUID = 1L; - @Id @SequenceGenerator(name = "seq", sequenceName = "cargotracker_seq", allocationSize = 50) @GeneratedValue (strategy = GenerationType.AUTO, generator = "seq") diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/location/Location.java b/src/main/java/org/eclipse/cargotracker/domain/model/location/Location.java index 056ab71..204a000 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/location/Location.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/location/Location.java @@ -7,10 +7,10 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.NamedQuery; -import javax.persistence.SequenceGenerator; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import org.apache.commons.lang3.Validate; +import javax.persistence.SequenceGenerator; /** * A location in our model is stops on a journey, such as cargo origin or destination, or carrier @@ -29,7 +29,7 @@ public class Location implements Serializable { // Special Location object that marks an unknown location. public static final Location UNKNOWN = new Location(new UnLocode("XXXXX"), "Unknown location"); - + @Id @SequenceGenerator(name = "seq", sequenceName = "cargotracker_seq", allocationSize = 50) @GeneratedValue (strategy = GenerationType.AUTO, generator = "seq") diff --git a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/CarrierMovement.java b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/CarrierMovement.java index c737d57..88e885d 100644 --- a/src/main/java/org/eclipse/cargotracker/domain/model/voyage/CarrierMovement.java +++ b/src/main/java/org/eclipse/cargotracker/domain/model/voyage/CarrierMovement.java @@ -29,7 +29,6 @@ public class CarrierMovement implements Serializable { public static final CarrierMovement NONE = new CarrierMovement(Location.UNKNOWN, Location.UNKNOWN, LocalDateTime.MIN, LocalDateTime.MIN); - @Id @SequenceGenerator(name = "seq", sequenceName = "cargotracker_seq", allocationSize = 50) @GeneratedValue (strategy = GenerationType.AUTO, generator = "seq") diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/JmsQueueNames.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/JmsQueueNames.java deleted file mode 100644 index 5a1f415..0000000 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/JmsQueueNames.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.eclipse.cargotracker.infrastructure.messaging; - -// for Open liberty. -// removed the global prefix. -public class JmsQueueNames { - public static final String CARGO_HANDLED_QUEUE = "jms/CargoHandledQueue"; - public static final String MISDIRECTED_CARGO_QUEUE = "jms/MisdirectedCargoQueue"; - public static final String DELIVERED_CARGO_QUEUE = "jms/DeliveredCargoQueue"; - public static final String REJECTED_REGISTRATION_ATTEMPTS_QUEUE = - "jms/RejectedRegistrationAttemptsQueue"; - public static final String HANDLING_EVENT_REGISTRATION_ATTEMPT_QUEUE = - "jms/HandlingEventRegistrationAttemptQueue"; - - private JmsQueueNames() {} -} \ No newline at end of file diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/CargoHandledConsumer.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/CargoHandledConsumer.java index 546cf84..903171a 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/CargoHandledConsumer.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/CargoHandledConsumer.java @@ -11,7 +11,6 @@ import javax.jms.TextMessage; import org.eclipse.cargotracker.application.CargoInspectionService; import org.eclipse.cargotracker.domain.model.cargo.TrackingId; -import org.eclipse.cargotracker.infrastructure.messaging.JmsQueueNames; /** * Consumes JMS messages and delegates notification of misdirected cargo to the tracking service. @@ -26,7 +25,7 @@ propertyValue = "javax.jms.Queue"), @ActivationConfigProperty( propertyName = "destinationLookup", - propertyValue = JmsQueueNames.CARGO_HANDLED_QUEUE) + propertyValue = "java:app/jms/CargoHandledQueue") }) public class CargoHandledConsumer implements MessageListener { diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/DeliveredCargoConsumer.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/DeliveredCargoConsumer.java index ead5b47..38d1118 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/DeliveredCargoConsumer.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/DeliveredCargoConsumer.java @@ -9,8 +9,6 @@ import javax.jms.Message; import javax.jms.MessageListener; -import org.eclipse.cargotracker.infrastructure.messaging.JmsQueueNames; - @MessageDriven( activationConfig = { @ActivationConfigProperty( @@ -18,7 +16,7 @@ propertyValue = "javax.jms.Queue"), @ActivationConfigProperty( propertyName = "destinationLookup", - propertyValue = JmsQueueNames.DELIVERED_CARGO_QUEUE) + propertyValue = "java:app/jms/DeliveredCargoQueue") }) public class DeliveredCargoConsumer implements MessageListener { diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/HandlingEventRegistrationAttemptConsumer.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/HandlingEventRegistrationAttemptConsumer.java index ea09acd..ef90e16 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/HandlingEventRegistrationAttemptConsumer.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/HandlingEventRegistrationAttemptConsumer.java @@ -9,7 +9,6 @@ import javax.jms.ObjectMessage; import org.eclipse.cargotracker.application.HandlingEventService; import org.eclipse.cargotracker.domain.model.handling.CannotCreateHandlingEventException; -import org.eclipse.cargotracker.infrastructure.messaging.JmsQueueNames; import org.eclipse.cargotracker.interfaces.handling.HandlingEventRegistrationAttempt; /** Consumes handling event registration attempt messages and delegates to proper registration. */ @@ -20,7 +19,7 @@ propertyValue = "javax.jms.Queue"), @ActivationConfigProperty( propertyName = "destinationLookup", - propertyValue = JmsQueueNames.HANDLING_EVENT_REGISTRATION_ATTEMPT_QUEUE) + propertyValue = "java:app/jms/HandlingEventRegistrationAttemptQueue") }) public class HandlingEventRegistrationAttemptConsumer implements MessageListener { diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/JmsApplicationEvents.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/JmsApplicationEvents.java index 6fea572..a85c62c 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/JmsApplicationEvents.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/JmsApplicationEvents.java @@ -7,12 +7,10 @@ import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import javax.jms.Destination; -import javax.jms.JMSConnectionFactory; import javax.jms.JMSContext; import org.eclipse.cargotracker.application.ApplicationEvents; import org.eclipse.cargotracker.domain.model.cargo.Cargo; import org.eclipse.cargotracker.domain.model.handling.HandlingEvent; -import org.eclipse.cargotracker.infrastructure.messaging.JmsQueueNames; import org.eclipse.cargotracker.interfaces.handling.HandlingEventRegistrationAttempt; @ApplicationScoped @@ -20,20 +18,18 @@ public class JmsApplicationEvents implements ApplicationEvents, Serializable { private static final long serialVersionUID = 1L; private static final int LOW_PRIORITY = 0; - @Inject - @JMSConnectionFactory("java:comp/DefaultJMSConnectionFactory") - JMSContext jmsContext; + @Inject JMSContext jmsContext; - @Resource(lookup = JmsQueueNames.CARGO_HANDLED_QUEUE) + @Resource(lookup = "java:app/jms/CargoHandledQueue") private Destination cargoHandledQueue; - @Resource(lookup = JmsQueueNames.MISDIRECTED_CARGO_QUEUE) + @Resource(lookup = "java:app/jms/MisdirectedCargoQueue") private Destination misdirectedCargoQueue; - @Resource(lookup = JmsQueueNames.DELIVERED_CARGO_QUEUE) + @Resource(lookup = "java:app/jms/DeliveredCargoQueue") private Destination deliveredCargoQueue; - @Resource(lookup = JmsQueueNames.HANDLING_EVENT_REGISTRATION_ATTEMPT_QUEUE) + @Resource(lookup = "java:app/jms/HandlingEventRegistrationAttemptQueue") private Destination handlingEventQueue; @Inject private Logger logger; diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/MisdirectedCargoConsumer.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/MisdirectedCargoConsumer.java index c15c016..9271e0f 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/MisdirectedCargoConsumer.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/MisdirectedCargoConsumer.java @@ -9,8 +9,6 @@ import javax.jms.Message; import javax.jms.MessageListener; -import org.eclipse.cargotracker.infrastructure.messaging.JmsQueueNames; - @MessageDriven( activationConfig = { @ActivationConfigProperty( @@ -18,7 +16,7 @@ propertyValue = "javax.jms.Queue"), @ActivationConfigProperty( propertyName = "destinationLookup", - propertyValue = JmsQueueNames.MISDIRECTED_CARGO_QUEUE) + propertyValue = "java:app/jms/MisdirectedCargoQueue") }) public class MisdirectedCargoConsumer implements MessageListener { diff --git a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/RejectedRegistrationAttemptsConsumer.java b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/RejectedRegistrationAttemptsConsumer.java index 6cca2e0..5d33d56 100644 --- a/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/RejectedRegistrationAttemptsConsumer.java +++ b/src/main/java/org/eclipse/cargotracker/infrastructure/messaging/jms/RejectedRegistrationAttemptsConsumer.java @@ -9,8 +9,6 @@ import javax.jms.Message; import javax.jms.MessageListener; -import org.eclipse.cargotracker.infrastructure.messaging.JmsQueueNames; - @MessageDriven( activationConfig = { @ActivationConfigProperty( @@ -18,7 +16,7 @@ propertyValue = "javax.jms.Queue"), @ActivationConfigProperty( propertyName = "destinationLookup", - propertyValue = JmsQueueNames.REJECTED_REGISTRATION_ATTEMPTS_QUEUE) + propertyValue = "java:app/jms/RejectedRegistrationAttemptsQueue") }) public class RejectedRegistrationAttemptsConsumer implements MessageListener { diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/sse/RealtimeCargoTrackingService.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/sse/RealtimeCargoTrackingService.java index 77f2582..b3849c0 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/sse/RealtimeCargoTrackingService.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/sse/RealtimeCargoTrackingService.java @@ -2,11 +2,12 @@ import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; -import javax.inject.Singleton; +import javax.ejb.Singleton; import javax.enterprise.event.ObservesAsync; import javax.inject.Inject; +import javax.naming.InitialContext; +import javax.naming.NamingException; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @@ -29,32 +30,42 @@ public class RealtimeCargoTrackingService { @Inject private CargoRepository cargoRepository; @Context private Sse sse; - private SseBroadcaster broadcaster; - @PostConstruct - public void init() { - broadcaster = sse.newBroadcaster(); - logger.log(Level.FINEST, "SSE broadcaster created."); - } + private SseBroadcaster broadcaster; @GET @Produces(MediaType.SERVER_SENT_EVENTS) public void tracking(@Context SseEventSink eventSink) { + synchronized (RealtimeCargoTrackingService.class) { + try { + String name = "java:app/jms/CargoHandledQueue"; + InitialContext ctx = new InitialContext(); + Object obj = InitialContext.doLookup(name); + } catch (NamingException e) { + e.printStackTrace(); + } + if (broadcaster == null) { + broadcaster = sse.newBroadcaster(); + } + } cargoRepository.findAll().stream().map(this::cargoToSseEvent).forEach(eventSink::send); - broadcaster.register(eventSink); logger.log(Level.FINEST, "SSE event sink registered."); } @PreDestroy public void close() { - broadcaster.close(); - logger.log(Level.FINEST, "SSE broadcaster closed."); + if (broadcaster != null) { + broadcaster.close(); + logger.log(Level.FINEST, "SSE broadcaster closed."); + } } public void onCargoUpdated(@ObservesAsync @CargoUpdated Cargo cargo) { - logger.log(Level.FINEST, "SSE event broadcast for cargo: {0}", cargo); - broadcaster.broadcast(cargoToSseEvent(cargo)); + if (broadcaster != null && (sse.newEventBuilder() != null)) { + logger.log(Level.FINEST, "SSE event broadcast for cargo: {0}", cargo); + broadcaster.broadcast(cargoToSseEvent(cargo)); + } } private OutboundSseEvent cargoToSseEvent(Cargo cargo) { diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Booking.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Booking.java index 3165456..829bfa3 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Booking.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Booking.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.List; import javax.annotation.PostConstruct; -import javax.enterprise.context.SessionScoped; import javax.faces.application.FacesMessage; import javax.faces.context.FacesContext; import javax.faces.flow.FlowScoped; @@ -27,8 +26,7 @@ * polarized ways to build user interfaces. */ @Named -// @FlowScoped("booking") -@SessionScoped +@FlowScoped("booking") public class Booking implements Serializable { private static final long serialVersionUID = 1L; diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Track.java b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Track.java index 2e4fd16..c11979f 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Track.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/booking/web/Track.java @@ -19,7 +19,7 @@ * there is never any one perfect solution for all situations, so we've chosen to demonstrate two * polarized ways to build user interfaces. */ -@Named("adminTrack") +@Named("admin.track") @ViewScoped public class Track implements Serializable { diff --git a/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/Track.java b/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/Track.java index 5c94381..b059d98 100644 --- a/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/Track.java +++ b/src/main/java/org/eclipse/cargotracker/interfaces/tracking/web/Track.java @@ -29,7 +29,7 @@ * *

In some very simplistic cases, it is fine to not use even an adapter. */ -@Named("publicTrack") +@Named("public.track") @ViewScoped public class Track implements Serializable { diff --git a/src/main/liberty/aks/app-insight.yaml b/src/main/liberty/aks/app-insight.yaml new file mode 100644 index 0000000..45931de --- /dev/null +++ b/src/main/liberty/aks/app-insight.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: app-insight-secret + namespace: ${param.namespace} +type: Opaque +stringData: + connection.string: "${param.app.insight.connection.string}" \ No newline at end of file diff --git a/src/main/liberty/aks/openlibertyapplication.yaml b/src/main/liberty/aks/openlibertyapplication.yaml index 71e3854..b52ce33 100644 --- a/src/main/liberty/aks/openlibertyapplication.yaml +++ b/src/main/liberty/aks/openlibertyapplication.yaml @@ -8,31 +8,57 @@ spec: applicationImage: ${param.login.server}/${project.artifactId}:${project.version} pullPolicy: Always service: - type: LoadBalancer + type: ClusterIP port: 9080 env: - - name: DB_SERVER_NAME - valueFrom: - secretKeyRef: - name: db-secret-sql - key: db.server.name - - name: DB_PORT_NUMBER - valueFrom: - secretKeyRef: - name: db-secret-sql - key: db.port.number - - name: DB_NAME - valueFrom: - secretKeyRef: - name: db-secret-sql - key: db.name - - name: DB_USER - valueFrom: - secretKeyRef: - name: db-secret-sql - key: db.user - - name: DB_PASSWORD - valueFrom: - secretKeyRef: - name: db-secret-sql - key: db.password + - name: DB_SERVER_NAME + valueFrom: + secretKeyRef: + name: db-secret-sql + key: db.server.name + - name: DB_PORT_NUMBER + valueFrom: + secretKeyRef: + name: db-secret-sql + key: db.port.number + - name: DB_NAME + valueFrom: + secretKeyRef: + name: db-secret-sql + key: db.name + - name: DB_USER + valueFrom: + secretKeyRef: + name: db-secret-sql + key: db.user + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: db-secret-sql + key: db.password + - name: APPLICATIONINSIGHTS_CONNECTION_STRING + valueFrom: + secretKeyRef: + name: app-insight-secret + key: connection.string +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ${project.artifactId}-ingress + namespace: default + annotations: + kubernetes.io/ingress.class: azure/application-gateway + appgw.ingress.kubernetes.io/cookie-based-affinity: "true" + appgw.ingress.kubernetes.io/use-private-ip: "false" +spec: + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: ${project.artifactId}-cluster + port: + number: 9080 diff --git a/src/main/liberty/config/bootstrap.properties b/src/main/liberty/config/bootstrap.properties new file mode 100644 index 0000000..c3ad1e9 --- /dev/null +++ b/src/main/liberty/config/bootstrap.properties @@ -0,0 +1,4 @@ +org.apache.el.parser.SKIP_IDENTIFIER_CHECK=true +com.ibm.ws.logging.max.file.size=100 +com.ibm.ws.logging.max.files=3 +# com.ibm.ws.logging.trace.specification=*=info=enabled:logservice=all:com.ibm.ws.jaxrs*=all:com.ibm.websphere.jaxrs*=all:org.apache.cxf.*=all:EJBContainer=all:Injection=all diff --git a/src/main/liberty/config/jvm.options b/src/main/liberty/config/jvm.options new file mode 100644 index 0000000..0782a5c --- /dev/null +++ b/src/main/liberty/config/jvm.options @@ -0,0 +1,3 @@ +# https://www.ibm.com/docs/en/was-liberty/core?topic=manually-customizing-liberty-environment + +-javaagent:/config/applicationinsights-agent.jar \ No newline at end of file diff --git a/src/main/liberty/config/server.xml b/src/main/liberty/config/server.xml index c116cc9..d71a97d 100644 --- a/src/main/liberty/config/server.xml +++ b/src/main/liberty/config/server.xml @@ -2,35 +2,41 @@ - cdi-2.0 - jaxb-2.2 - jsf-2.3 - jaxrs-2.1 - ejbLite-3.2 - jpa-2.2 - jms-2.0 wasJmsClient-2.0 - wasJmsSecurity-1.0 wasJmsServer-1.0 + jsonb-1.0 + ejbLite-3.2 + beanValidation-2.0 + jsf-2.3 jndi-1.0 + cdi-2.0 + jdbc-4.2 + jms-2.0 + ejbPersistentTimer-3.2 + jaxrs-2.1 + jaxb-2.2 mdb-3.2 + batch-1.0 + jpa-2.2 - - - - + + + + - - + + + + + + - - - + + - + - + - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + - - + + + + + + + - + - - - - - + + + + + + + + + + + + - + - - + + + + + + + - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/liberty/docker/Dockerfile b/src/main/liberty/docker/Dockerfile index 992dea8..f832777 100644 --- a/src/main/liberty/docker/Dockerfile +++ b/src/main/liberty/docker/Dockerfile @@ -1,10 +1,13 @@ # open liberty base image -FROM openliberty/open-liberty:full-java8-openj9-ubi +FROM openliberty/open-liberty:full-java11-openj9-ubi # Add config, app and jdbc driver COPY --chown=1001:0 liberty/wlp/usr/servers/defaultServer/server.xml /config/server.xml +COPY --chown=1001:0 liberty/wlp/usr/servers/defaultServer/jvm.options /config/jvm.options +COPY --chown=1001:0 liberty/wlp/usr/servers/defaultServer/bootstrap.properties /config/bootstrap.properties COPY --chown=1001:0 cargo-tracker.war /config/apps/ -COPY --chown=1001:0 liberty/wlp/usr/shared/resources/postgresql-42.2.4.jar /opt/ol/wlp/usr/shared/resources/ +COPY --chown=1001:0 liberty/wlp/usr/shared/resources/postgresql.jar /opt/ol/wlp/usr/shared/resources/ +COPY --chown=1001:0 liberty/wlp/usr/servers/defaultServer/applicationinsights-agent.jar /config/ # This script will add the requested XML snippets, grow image to be fit-for-purpose and apply interim fixes RUN configure.sh diff --git a/src/main/liberty/docker/Dockerfile-local b/src/main/liberty/docker/Dockerfile-local index 0ba1961..efefa6a 100644 --- a/src/main/liberty/docker/Dockerfile-local +++ b/src/main/liberty/docker/Dockerfile-local @@ -1,11 +1,11 @@ # open liberty base image -FROM openliberty/open-liberty:full-java8-openj9-ubi +FROM openliberty/open-liberty:full-java11-openj9-ubi # Add config, app and jdbc driver COPY --chown=1001:0 liberty/wlp/usr/servers/defaultServer/server.xml /config/server.xml -COPY --chown=1001:0 liberty/wlp/usr/servers/defaultServer/bootstrap.properties /config/bootstrap.properties COPY --chown=1001:0 ${project.artifactId}.war /config/apps/ -COPY --chown=1001:0 liberty/wlp/usr/shared/resources/postgresql-42.2.4.jar /opt/ol/wlp/usr/shared/resources/ +COPY --chown=1001:0 liberty/wlp/usr/shared/resources/postgresql.jar /opt/ol/wlp/usr/shared/resources/ +COPY --chown=1001:0 liberty/wlp/usr/servers/defaultServer/applicationinsights-agent.jar /config/ # This script will add the requested XML snippets, grow image to be fit-for-purpose and apply interim fixes RUN configure.sh diff --git a/src/main/liberty/jms/JmsApplicationEvents.java b/src/main/liberty/jms/JmsApplicationEvents.java deleted file mode 100644 index fc38c01..0000000 --- a/src/main/liberty/jms/JmsApplicationEvents.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.eclipse.cargotracker.infrastructure.messaging.jms; - -import java.io.Serializable; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.Resource; -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import javax.jms.Destination; -import javax.jms.JMSConnectionFactory; -import javax.jms.JMSContext; -import org.eclipse.cargotracker.application.ApplicationEvents; -import org.eclipse.cargotracker.domain.model.cargo.Cargo; -import org.eclipse.cargotracker.domain.model.handling.HandlingEvent; -import org.eclipse.cargotracker.infrastructure.messaging.JmsQueueNames; -import org.eclipse.cargotracker.interfaces.handling.HandlingEventRegistrationAttempt; - -@ApplicationScoped -public class JmsApplicationEvents implements ApplicationEvents, Serializable { - - private static final long serialVersionUID = 1L; - private static final int LOW_PRIORITY = 0; - @Inject - @JMSConnectionFactory("java:comp/DefaultJMSConnectionFactory") - JMSContext jmsContext; - - @Resource(lookup = JmsQueueNames.CARGO_HANDLED_QUEUE) - private Destination cargoHandledQueue; - - @Resource(lookup = JmsQueueNames.MISDIRECTED_CARGO_QUEUE) - private Destination misdirectedCargoQueue; - - @Resource(lookup = JmsQueueNames.DELIVERED_CARGO_QUEUE) - private Destination deliveredCargoQueue; - - @Resource(lookup = JmsQueueNames.HANDLING_EVENT_REGISTRATION_ATTEMPT_QUEUE) - private Destination handlingEventQueue; - - @Inject private Logger logger; - - @Override - public void cargoWasHandled(HandlingEvent event) { - Cargo cargo = event.getCargo(); - logger.log(Level.INFO, "Cargo was handled {0}", cargo); - jmsContext - .createProducer() - .setPriority(LOW_PRIORITY) - .setDisableMessageID(true) - .setDisableMessageTimestamp(true) - .send(cargoHandledQueue, cargo.getTrackingId().getIdString()); - } - - @Override - public void cargoWasMisdirected(Cargo cargo) { - logger.log(Level.INFO, "Cargo was misdirected {0}", cargo); - jmsContext - .createProducer() - .setPriority(LOW_PRIORITY) - .setDisableMessageID(true) - .setDisableMessageTimestamp(true) - .send(misdirectedCargoQueue, cargo.getTrackingId().getIdString()); - } - - @Override - public void cargoHasArrived(Cargo cargo) { - logger.log(Level.INFO, "Cargo has arrived {0}", cargo); - jmsContext - .createProducer() - .setPriority(LOW_PRIORITY) - .setDisableMessageID(true) - .setDisableMessageTimestamp(true) - .send(deliveredCargoQueue, cargo.getTrackingId().getIdString()); - } - - @Override - public void receivedHandlingEventRegistrationAttempt(HandlingEventRegistrationAttempt attempt) { - logger.log(Level.INFO, "Received handling event registration attempt {0}", attempt); - jmsContext - .createProducer() - .setPriority(LOW_PRIORITY) - .setDisableMessageID(true) - .setDisableMessageTimestamp(true) - .setTimeToLive(1000) - .send(handlingEventQueue, attempt); - } -} diff --git a/src/main/liberty/jms/JmsQueueNames.java b/src/main/liberty/jms/JmsQueueNames.java deleted file mode 100644 index 1fd9923..0000000 --- a/src/main/liberty/jms/JmsQueueNames.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.eclipse.cargotracker.infrastructure.messaging; - -// for Open liberty. -// removed the global prefix. -public class JmsQueueNames { - public static final String CARGO_HANDLED_QUEUE = "jms/CargoHandledQueue"; - public static final String MISDIRECTED_CARGO_QUEUE = "jms/MisdirectedCargoQueue"; - public static final String DELIVERED_CARGO_QUEUE = "jms/DeliveredCargoQueue"; - public static final String REJECTED_REGISTRATION_ATTEMPTS_QUEUE = - "jms/RejectedRegistrationAttemptsQueue"; - public static final String HANDLING_EVENT_REGISTRATION_ATTEMPT_QUEUE = - "jms/HandlingEventRegistrationAttemptQueue"; - - private JmsQueueNames() {} -} diff --git a/src/main/webapp/WEB-INF/faces-config.xml b/src/main/webapp/WEB-INF/faces-config.xml index 49d6049..5ab3c79 100644 --- a/src/main/webapp/WEB-INF/faces-config.xml +++ b/src/main/webapp/WEB-INF/faces-config.xml @@ -1,14 +1,11 @@ - - - - org.eclipse.cargotracker.messages - messages - - org.primefaces.application.DialogActionListener - org.primefaces.application.DialogNavigationHandler - org.primefaces.application.DialogViewHandler - + + + org.primefaces.application.DialogActionListener + org.primefaces.application.DialogNavigationHandler + org.primefaces.application.DialogViewHandler + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/templates/common/admin.xhtml b/src/main/webapp/WEB-INF/templates/common/admin.xhtml index f840b6e..acb2321 100644 --- a/src/main/webapp/WEB-INF/templates/common/admin.xhtml +++ b/src/main/webapp/WEB-INF/templates/common/admin.xhtml @@ -24,16 +24,14 @@