├── .devcontainer └── devcontainer.json ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── quarkus-micronaut ├── 00-setup-your-environment │ └── README.md ├── 01-build-a-simple-java-application │ ├── README.md │ ├── micronaut-simple-application │ │ ├── .gitignore │ │ ├── .mvn │ │ │ └── wrapper │ │ │ │ └── maven-wrapper.properties │ │ ├── README.md │ │ ├── aot-jar.properties │ │ ├── micronaut-cli.yml │ │ ├── mvnw │ │ ├── mvnw.bat │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ ├── Application.java │ │ │ │ │ └── HelloController.java │ │ │ └── resources │ │ │ │ ├── application.properties │ │ │ │ └── logback.xml │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── MicronautSimpleApplicationTest.java │ └── quarkus-simple-application │ │ ├── .dockerignore │ │ ├── .gitignore │ │ ├── .mvn │ │ └── wrapper │ │ │ ├── .gitignore │ │ │ ├── MavenWrapperDownloader.java │ │ │ └── maven-wrapper.properties │ │ ├── README.md │ │ ├── mvnw │ │ ├── mvnw.cmd │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── docker │ │ │ ├── Dockerfile.jvm │ │ │ ├── Dockerfile.legacy-jar │ │ │ ├── Dockerfile.native │ │ │ └── Dockerfile.native-micro │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── GreetingResource.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ ├── GreetingResourceIT.java │ │ └── GreetingResourceTest.java ├── 02-build-a-reactive-and-native-quarkus-microservice-using-postgresql │ ├── README.md │ └── city-service │ │ ├── .dockerignore │ │ ├── .gitignore │ │ ├── .mvn │ │ └── wrapper │ │ │ ├── .gitignore │ │ │ ├── MavenWrapperDownloader.java │ │ │ └── maven-wrapper.properties │ │ ├── README.md │ │ ├── mvnw │ │ ├── mvnw.cmd │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── docker │ │ │ ├── Dockerfile.jvm │ │ │ ├── Dockerfile.legacy-jar │ │ │ ├── Dockerfile.native │ │ │ └── Dockerfile.native-micro │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── City.java │ │ │ │ └── CityResource.java │ │ └── resources │ │ │ ├── META-INF │ │ │ └── resources │ │ │ │ └── index.html │ │ │ ├── application.properties │ │ │ └── db │ │ │ └── changeLog.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ ├── CityResourceIT.java │ │ └── CityResourceTest.java ├── 03-build-a-micronaut-microservice-using-mysql │ ├── README.md │ └── weather-service │ │ ├── .gitignore │ │ ├── .mvn │ │ └── wrapper │ │ │ └── maven-wrapper.properties │ │ ├── Dockerfile-otel-agent │ │ ├── README.md │ │ ├── aot-jar.properties │ │ ├── aot-native-image.properties │ │ ├── micronaut-cli.yml │ │ ├── mvnw │ │ ├── mvnw.bat │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ ├── Application.java │ │ │ │ ├── WeatherController.java │ │ │ │ ├── WeatherRepository.java │ │ │ │ └── domain │ │ │ │ └── Weather.java │ │ └── resources │ │ │ ├── application.properties │ │ │ ├── db │ │ │ └── migration │ │ │ │ └── V1__schema.sql │ │ │ └── logback.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── WeatherServiceTest.java ├── 04-build-a-nginx-reverse-proxy │ ├── README.md │ └── gateway │ │ ├── Dockerfile │ │ └── nginx │ │ ├── entrypoint.sh │ │ └── nginx.conf.template ├── 05-putting-it-all-together-a-complete-microservice-stack │ ├── README.md │ ├── media │ │ └── 01-vuejs-frontend.png │ └── weather-app │ │ ├── .browserslistrc │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── docker │ │ └── entrypoint.sh │ │ ├── eslint.config.mjs │ │ ├── index.html │ │ ├── jsconfig.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ └── favicon.ico │ │ ├── src │ │ ├── App.vue │ │ ├── components │ │ │ └── WeatherComponent.vue │ │ ├── main.js │ │ └── plugins │ │ │ ├── README.md │ │ │ ├── index.js │ │ │ └── vuetify.js │ │ └── vite.config.mjs ├── 06-build-a-quarkus-ai-application-using-azure-openai │ ├── README.md │ ├── ai-weather-application │ │ ├── .dockerignore │ │ ├── .gitignore │ │ ├── .mvn │ │ │ └── wrapper │ │ │ │ ├── .gitignore │ │ │ │ ├── MavenWrapperDownloader.java │ │ │ │ └── maven-wrapper.properties │ │ ├── README.md │ │ ├── mvnw │ │ ├── mvnw.cmd │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── docker │ │ │ │ ├── Dockerfile.jvm │ │ │ │ ├── Dockerfile.legacy-jar │ │ │ │ ├── Dockerfile.native │ │ │ │ └── Dockerfile.native-micro │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ ├── AiWeatherResource.java │ │ │ │ │ └── AiWeatherService.java │ │ │ └── resources │ │ │ │ ├── META-INF │ │ │ │ └── resources │ │ │ │ │ └── index.html │ │ │ │ ├── Paris.csv │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ ├── AiWeatherResourceIT.java │ │ │ └── AiWeatherResourceTest.java │ └── media │ │ ├── 01-question.png │ │ ├── 02-question.png │ │ ├── 03-question.png │ │ └── 04-question.png └── README.md └── spring ├── 00-setup-your-environment ├── README.md ├── azuredeploy.json ├── azuredeploy.parameters.json └── media │ └── deploybutton.svg ├── 01-build-a-simple-java-application ├── README.md ├── media │ └── 01-application-url.png └── simple-application │ ├── .gitignore │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── demo │ │ │ ├── HelloController.java │ │ │ └── SimpleApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── demo │ └── SimpleApplicationTests.java ├── 02-create-managed-eureka-server-for-spring └── README.md ├── 03-create-and-configure-managed-config-server-for-spring ├── README.md └── media │ ├── 01-github-personal-access-token.png │ ├── 02-github-token-select-repositories.png │ ├── 03-github-repo-permission.png │ ├── 04-github-repo-permission-content-readonly.png │ └── 05-github-generate-token.png ├── 04-build-a-spring-boot-microservice-using-spring-cloud-features ├── README.md ├── media │ ├── 01-exception-stack-trace.png │ ├── 02-console-output.png │ └── 03-logs-query.png └── spring-cloud-microservice │ ├── .gitignore │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── demo │ │ │ ├── HelloController.java │ │ │ └── SpringCloudMicroserviceApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── demo │ └── SpringCloudMicroserviceApplicationTests.java ├── 05-build-a-reactive-spring-boot-microservice-using-cosmosdb ├── README.md ├── city-service │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── demo │ │ │ │ ├── City.java │ │ │ │ ├── CityController.java │ │ │ │ └── CityServiceApplication.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── demo │ │ └── CityServiceApplicationTests.java └── media │ ├── 01-data-explorer.png │ ├── 02-service-connector-cosmos.png │ ├── 03-service-connector-cosmos.png │ ├── 04-service-connector-cosmos.png │ └── 05-service-connector-cosmos.png ├── 06-build-a-spring-boot-microservice-using-mysql ├── README.md ├── media │ ├── 01-create-service-connector-mysql.png │ ├── 02-create-service-connector-mysql.png │ ├── 03-create-service-connector-mysql.png │ └── 04-create-service-connector-mysql.png └── weather-service │ ├── .gitignore │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── demo │ │ │ ├── Weather.java │ │ │ ├── WeatherController.java │ │ │ ├── WeatherRepository.java │ │ │ └── WeatherServiceApplication.java │ └── resources │ │ ├── application.properties │ │ └── import.sql │ └── test │ └── java │ └── com │ └── example │ └── demo │ └── WeatherServiceApplicationTests.java ├── 07-build-a-spring-cloud-gateway ├── README.md └── gateway │ ├── .gitignore │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── demo │ │ │ └── GatewayApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── demo │ └── GatewayApplicationTests.java ├── 08-putting-it-all-together-a-complete-microservice-stack ├── README.md ├── media │ └── 01-vuejs-frontend.png └── weather-app │ ├── .browserslistrc │ ├── .editorconfig │ ├── .gitignore │ ├── Dockerfile │ ├── README.md │ ├── docker │ └── entrypoint.sh │ ├── eslint.config.mjs │ ├── index.html │ ├── jsconfig.json │ ├── package-lock.json │ ├── package.json │ ├── public │ └── favicon.ico │ ├── src │ ├── App.vue │ ├── components │ │ └── WeatherComponent.vue │ ├── main.js │ └── plugins │ │ ├── README.md │ │ ├── index.js │ │ └── vuetify.js │ └── vite.config.mjs ├── 09-build-a-spring-ai-application-using-azure-openai ├── README.md ├── ai-weather-application │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── demo │ │ │ │ ├── AiWeatherApplication.java │ │ │ │ └── AiWeatherController.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── static │ │ │ ├── Paris.csv │ │ │ ├── index.html │ │ │ └── prompt.template │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── demo │ │ └── AiWeatherApplicationTests.java └── media │ ├── 01-question.png │ ├── 02-question.png │ ├── 03-question.png │ └── 04-question.png └── README.md /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": "mcr.microsoft.com/devcontainers/java:1-17-bullseye", 3 | "features": { 4 | "ghcr.io/devcontainers/features/azure-cli:1": {}, 5 | "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}, 6 | "ghcr.io/devcontainers/features/java:1": { 7 | "version": "17.0.11-graal", 8 | "installGradle": "true", 9 | "installMaven": "true", 10 | "jdkDistro": "graal" 11 | } 12 | }, 13 | "postCreateCommand": "echo '\n\nif [ -f \"$HOME/my_environment\" ]; then\n source \"$HOME/my_environment\"\nfi\n\nsaveenv() {\n # Check if var_save is set\n declare -p | grep -v \"declare -[a-z]*r\" > \"$HOME/my_environment\"\n}\n\nclearenv() {\n echo \"\" > \"$HOME/my_environment\"\n}' >> $HOME/.bashrc" 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | replay_pid* 25 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build, Run and Monitor Intelligent Java Apps on Azure Container Apps and Azure OpenAI 2 | 3 | ## What you should expect 4 | 5 | This is not the official documentation but an opinionated workshop. 6 | 7 | It is a hands-on training, and it will use the command line extensively. The idea is to get coding very quickly and play with the platform, from a simple demo to far more complex examples. 8 | 9 | After completing all the guides in [spring](spring) and [quarkus-micronaut](quarkus-micronaut), you should have a fairly good understanding of everything that Java on Azure Container Apps offers. 10 | 11 | ## [spring](spring) 12 | 13 | This series of guides focus on building Java applications using **Spring** framwork and running them on Azure Container Apps. It also covers how to use Azure OpenAI to build AI applications. 14 | 15 | ## [quarkus-micronaut](quarkus-micronaut) 16 | 17 | This series of guides focus on building Java applications using **Quarkus** and **Micronaut** frameworks and running them on Azure Container Apps. It also covers how to use Azure OpenAI to build AI applications. 18 | 19 | For a third path that shows using Quarkus only, please see [link to the new repo](https://github.com/Azure-Samples/java-on-aca-quarkus). 20 | 21 | --- 22 | 23 | ## Trademarks 24 | 25 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft 26 | trademarks or logos is subject to and must follow 27 | [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). 28 | Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. 29 | Any use of third-party trademarks or logos are subject to those third-party's policies. 30 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # TODO: The maintainer of this repo has not yet edited this file 2 | 3 | **REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project? 4 | 5 | - **No CSS support:** Fill out this template with information about how to file issues and get help. 6 | - **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps. 7 | - **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide. 8 | 9 | *Then remove this first heading from this SUPPORT.MD file before publishing your repo.* 10 | 11 | # Support 12 | 13 | ## How to file issues and get help 14 | 15 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 16 | issues before filing new issues to avoid duplicates. For new issues, file your bug or 17 | feature request as a new Issue. 18 | 19 | For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE 20 | FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER 21 | CHANNEL. WHERE WILL YOU HELP PEOPLE?**. 22 | 23 | ## Microsoft Support Policy 24 | 25 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 26 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/micronaut-simple-application/.gitignore: -------------------------------------------------------------------------------- 1 | Thumbs.db 2 | .DS_Store 3 | .gradle 4 | build/ 5 | target/ 6 | out/ 7 | .micronaut/ 8 | .idea 9 | *.iml 10 | *.ipr 11 | *.iws 12 | .project 13 | .settings 14 | .classpath 15 | .factorypath 16 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/micronaut-simple-application/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip 18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar 19 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/micronaut-simple-application/README.md: -------------------------------------------------------------------------------- 1 | ## Micronaut 4.5.0 Documentation 2 | 3 | - [User Guide](https://docs.micronaut.io/4.5.0/guide/index.html) 4 | - [API Reference](https://docs.micronaut.io/4.5.0/api/index.html) 5 | - [Configuration Reference](https://docs.micronaut.io/4.5.0/guide/configurationreference.html) 6 | - [Micronaut Guides](https://guides.micronaut.io/index.html) 7 | --- 8 | 9 | - [Micronaut Maven Plugin documentation](https://micronaut-projects.github.io/micronaut-maven-plugin/latest/) 10 | ## Feature maven-enforcer-plugin documentation 11 | 12 | - [https://maven.apache.org/enforcer/maven-enforcer-plugin/](https://maven.apache.org/enforcer/maven-enforcer-plugin/) 13 | 14 | 15 | ## Feature micronaut-aot documentation 16 | 17 | - [Micronaut AOT documentation](https://micronaut-projects.github.io/micronaut-aot/latest/guide/) 18 | 19 | 20 | ## Feature serialization-jackson documentation 21 | 22 | - [Micronaut Serialization Jackson Core documentation](https://micronaut-projects.github.io/micronaut-serialization/latest/guide/) 23 | 24 | 25 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/micronaut-simple-application/aot-jar.properties: -------------------------------------------------------------------------------- 1 | # AOT configuration properties for jar packaging 2 | # Please review carefully the optimizations enabled below 3 | # Check https://micronaut-projects.github.io/micronaut-aot/latest/guide/ for more details 4 | 5 | # Caches environment property values: environment properties will be deemed immutable after application startup. 6 | cached.environment.enabled=true 7 | 8 | # Precomputes Micronaut configuration property keys from the current environment variables 9 | precompute.environment.properties.enabled=true 10 | 11 | # Replaces logback.xml with a pure Java configuration 12 | logback.xml.to.java.enabled=true 13 | 14 | # Converts YAML configuration files to Java configuration 15 | yaml.to.java.config.enabled=true 16 | 17 | # Scans for service types ahead-of-time, avoiding classpath scanning at startup 18 | serviceloading.jit.enabled=true 19 | 20 | # Scans reactive types at build time instead of runtime 21 | scan.reactive.types.enabled=true 22 | 23 | # Deduces the environment at build time instead of runtime 24 | deduce.environment.enabled=true 25 | 26 | # Checks of existence of some types at build time instead of runtime 27 | known.missing.types.enabled=true 28 | 29 | # Precomputes property sources at build time 30 | sealed.property.source.enabled=true 31 | 32 | # The list of service types to be scanned (comma separated) 33 | service.types=io.micronaut.context.env.PropertySourceLoader,io.micronaut.inject.BeanConfiguration,io.micronaut.inject.BeanDefinitionReference,io.micronaut.http.HttpRequestFactory,io.micronaut.http.HttpResponseFactory,io.micronaut.core.beans.BeanIntrospectionReference,io.micronaut.core.convert.TypeConverterRegistrar,io.micronaut.context.env.PropertyExpressionResolver 34 | 35 | # A list of types that the AOT analyzer needs to check for existence (comma separated) 36 | known.missing.types.list=io.reactivex.Observable,reactor.core.publisher.Flux,kotlinx.coroutines.flow.Flow,io.reactivex.rxjava3.core.Flowable,io.reactivex.rxjava3.core.Observable,io.reactivex.Single,reactor.core.publisher.Mono,io.reactivex.Maybe,io.reactivex.rxjava3.core.Single,io.reactivex.rxjava3.core.Maybe,io.reactivex.Completable,io.reactivex.rxjava3.core.Completable,io.methvin.watchservice.MacOSXListeningWatchService,io.micronaut.core.async.publisher.CompletableFuturePublisher,io.micronaut.core.async.publisher.Publishers.JustPublisher,io.micronaut.core.async.subscriber.Completable 37 | 38 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/micronaut-simple-application/micronaut-cli.yml: -------------------------------------------------------------------------------- 1 | applicationType: default 2 | defaultPackage: com.example 3 | testFramework: junit 4 | sourceLanguage: java 5 | buildTool: maven 6 | features: [app-name, http-client-test, java, java-application, junit, logback, maven, maven-enforcer-plugin, micronaut-aot, micronaut-http-validation, netty-server, properties, readme, serialization-jackson, shade, static-resources] 7 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/micronaut-simple-application/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.example 6 | micronaut-simple-application 7 | 0.1 8 | ${packaging} 9 | 10 | 11 | io.micronaut.platform 12 | micronaut-parent 13 | 4.5.0 14 | 15 | 16 | jar 17 | 17 18 | 17 19 | 4.5.0 20 | false 21 | com.example.aot.generated 22 | netty 23 | com.example.Application 24 | 25 | 26 | 27 | 28 | central 29 | https://repo.maven.apache.org/maven2 30 | 31 | 32 | 33 | 34 | 35 | io.micronaut 36 | micronaut-http-server-netty 37 | compile 38 | 39 | 40 | io.micronaut.serde 41 | micronaut-serde-jackson 42 | compile 43 | 44 | 45 | ch.qos.logback 46 | logback-classic 47 | runtime 48 | 49 | 50 | io.micronaut 51 | micronaut-http-client 52 | test 53 | 54 | 55 | io.micronaut.test 56 | micronaut-test-junit5 57 | test 58 | 59 | 60 | org.junit.jupiter 61 | junit-jupiter-api 62 | test 63 | 64 | 65 | org.junit.jupiter 66 | junit-jupiter-engine 67 | test 68 | 69 | 70 | 71 | 72 | 73 | io.micronaut.maven 74 | micronaut-maven-plugin 75 | 76 | aot-${packaging}.properties 77 | 78 | 79 | 80 | org.apache.maven.plugins 81 | maven-enforcer-plugin 82 | 83 | 84 | org.apache.maven.plugins 85 | maven-compiler-plugin 86 | 87 | 88 | 89 | 90 | 91 | 92 | io.micronaut 93 | micronaut-http-validation 94 | ${micronaut.core.version} 95 | 96 | 97 | io.micronaut.serde 98 | micronaut-serde-processor 99 | ${micronaut.serialization.version} 100 | 101 | 102 | io.micronaut 103 | micronaut-inject 104 | 105 | 106 | 107 | 108 | 109 | -Amicronaut.processing.group=com.example 110 | -Amicronaut.processing.module=micronaut-simple-application 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/micronaut-simple-application/src/main/java/com/example/Application.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.micronaut.runtime.Micronaut; 4 | 5 | public class Application { 6 | 7 | public static void main(String[] args) { 8 | Micronaut.run(Application.class, args); 9 | } 10 | } -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/micronaut-simple-application/src/main/java/com/example/HelloController.java: -------------------------------------------------------------------------------- 1 | package example.micronaut; 2 | 3 | import io.micronaut.http.MediaType; 4 | import io.micronaut.http.annotation.Controller; 5 | import io.micronaut.http.annotation.Get; 6 | import io.micronaut.http.annotation.Produces; 7 | 8 | @Controller("/hello") 9 | public class HelloController { 10 | @Get 11 | @Produces(MediaType.TEXT_PLAIN) 12 | public String hello() { 13 | return "Hello from Micronaut REST"; 14 | } 15 | } -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/micronaut-simple-application/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 21 00:42:42 UTC 2024 2 | micronaut.application.name=micronaut-simple-application 3 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/micronaut-simple-application/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/micronaut-simple-application/src/test/java/com/example/MicronautSimpleApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.micronaut.runtime.EmbeddedApplication; 4 | import io.micronaut.test.extensions.junit5.annotation.MicronautTest; 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.Assertions; 7 | 8 | import jakarta.inject.Inject; 9 | 10 | @MicronautTest 11 | class MicronautSimpleApplicationTest { 12 | 13 | @Inject 14 | EmbeddedApplication application; 15 | 16 | @Test 17 | void testItWorks() { 18 | Assertions.assertTrue(application.isRunning()); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !target/*-runner 3 | !target/*-runner.jar 4 | !target/lib/* 5 | !target/quarkus-app/* -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/.gitignore: -------------------------------------------------------------------------------- 1 | #Maven 2 | target/ 3 | pom.xml.tag 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | release.properties 7 | .flattened-pom.xml 8 | 9 | # Eclipse 10 | .project 11 | .classpath 12 | .settings/ 13 | bin/ 14 | 15 | # IntelliJ 16 | .idea 17 | *.ipr 18 | *.iml 19 | *.iws 20 | 21 | # NetBeans 22 | nb-configuration.xml 23 | 24 | # Visual Studio Code 25 | .vscode 26 | .factorypath 27 | 28 | # OSX 29 | .DS_Store 30 | 31 | # Vim 32 | *.swp 33 | *.swo 34 | 35 | # patch 36 | *.orig 37 | *.rej 38 | 39 | # Local environment 40 | .env 41 | 42 | # Plugin directory 43 | /.quarkus/cli/plugins/ 44 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/.mvn/wrapper/.gitignore: -------------------------------------------------------------------------------- 1 | maven-wrapper.jar 2 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.net.Authenticator; 23 | import java.net.PasswordAuthentication; 24 | import java.net.URL; 25 | import java.nio.file.Files; 26 | import java.nio.file.Path; 27 | import java.nio.file.Paths; 28 | import java.nio.file.StandardCopyOption; 29 | 30 | public final class MavenWrapperDownloader 31 | { 32 | private static final String WRAPPER_VERSION = "3.2.0"; 33 | 34 | private static final boolean VERBOSE = Boolean.parseBoolean( System.getenv( "MVNW_VERBOSE" ) ); 35 | 36 | public static void main( String[] args ) 37 | { 38 | log( "Apache Maven Wrapper Downloader " + WRAPPER_VERSION ); 39 | 40 | if ( args.length != 2 ) 41 | { 42 | System.err.println( " - ERROR wrapperUrl or wrapperJarPath parameter missing" ); 43 | System.exit( 1 ); 44 | } 45 | 46 | try 47 | { 48 | log( " - Downloader started" ); 49 | final URL wrapperUrl = new URL( args[0] ); 50 | final String jarPath = args[1].replace( "..", "" ); // Sanitize path 51 | final Path wrapperJarPath = Paths.get( jarPath ).toAbsolutePath().normalize(); 52 | downloadFileFromURL( wrapperUrl, wrapperJarPath ); 53 | log( "Done" ); 54 | } 55 | catch ( IOException e ) 56 | { 57 | System.err.println( "- Error downloading: " + e.getMessage() ); 58 | if ( VERBOSE ) 59 | { 60 | e.printStackTrace(); 61 | } 62 | System.exit( 1 ); 63 | } 64 | } 65 | 66 | private static void downloadFileFromURL( URL wrapperUrl, Path wrapperJarPath ) 67 | throws IOException 68 | { 69 | log( " - Downloading to: " + wrapperJarPath ); 70 | if ( System.getenv( "MVNW_USERNAME" ) != null && System.getenv( "MVNW_PASSWORD" ) != null ) 71 | { 72 | final String username = System.getenv( "MVNW_USERNAME" ); 73 | final char[] password = System.getenv( "MVNW_PASSWORD" ).toCharArray(); 74 | Authenticator.setDefault( new Authenticator() 75 | { 76 | @Override 77 | protected PasswordAuthentication getPasswordAuthentication() 78 | { 79 | return new PasswordAuthentication( username, password ); 80 | } 81 | } ); 82 | } 83 | try ( InputStream inStream = wrapperUrl.openStream() ) 84 | { 85 | Files.copy( inStream, wrapperJarPath, StandardCopyOption.REPLACE_EXISTING ); 86 | } 87 | log( " - Downloader complete" ); 88 | } 89 | 90 | private static void log( String msg ) 91 | { 92 | if ( VERBOSE ) 93 | { 94 | System.out.println( msg ); 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip 18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 19 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/README.md: -------------------------------------------------------------------------------- 1 | # quarkus-simple-application 2 | 3 | This project uses Quarkus, the Supersonic Subatomic Java Framework. 4 | 5 | If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ . 6 | 7 | ## Running the application in dev mode 8 | 9 | You can run your application in dev mode that enables live coding using: 10 | ```shell script 11 | ./mvnw compile quarkus:dev 12 | ``` 13 | 14 | > **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/. 15 | 16 | ## Packaging and running the application 17 | 18 | The application can be packaged using: 19 | ```shell script 20 | ./mvnw package 21 | ``` 22 | It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory. 23 | Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory. 24 | 25 | The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`. 26 | 27 | If you want to build an _über-jar_, execute the following command: 28 | ```shell script 29 | ./mvnw package -Dquarkus.package.jar.type=uber-jar 30 | ``` 31 | 32 | The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`. 33 | 34 | ## Creating a native executable 35 | 36 | You can create a native executable using: 37 | ```shell script 38 | ./mvnw package -Dnative 39 | ``` 40 | 41 | Or, if you don't have GraalVM installed, you can run the native executable build in a container using: 42 | ```shell script 43 | ./mvnw package -Dnative -Dquarkus.native.container-build=true 44 | ``` 45 | 46 | You can then execute your native executable with: `./target/quarkus-simple-application-1.0.0-SNAPSHOT-runner` 47 | 48 | If you want to learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling. 49 | 50 | ## Related Guides 51 | 52 | - REST ([guide](https://quarkus.io/guides/rest)): A Jakarta REST implementation utilizing build time processing and Vert.x. This extension is not compatible with the quarkus-resteasy extension, or any of the extensions that depend on it. 53 | 54 | ## Provided Code 55 | 56 | ### REST 57 | 58 | Easily start your REST Web Services 59 | 60 | [Related guide section...](https://quarkus.io/guides/getting-started-reactive#reactive-jax-rs-resources) 61 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.example 5 | quarkus-simple-application 6 | 1.0.0-SNAPSHOT 7 | 8 | 9 | 3.12.1 10 | 17 11 | UTF-8 12 | UTF-8 13 | quarkus-bom 14 | io.quarkus.platform 15 | 3.11.3 16 | true 17 | 3.2.5 18 | 19 | 20 | 21 | 22 | 23 | ${quarkus.platform.group-id} 24 | ${quarkus.platform.artifact-id} 25 | ${quarkus.platform.version} 26 | pom 27 | import 28 | 29 | 30 | 31 | 32 | 33 | 34 | io.quarkus 35 | quarkus-rest 36 | 37 | 38 | io.quarkus 39 | quarkus-arc 40 | 41 | 42 | io.quarkus 43 | quarkus-junit5 44 | test 45 | 46 | 47 | io.rest-assured 48 | rest-assured 49 | test 50 | 51 | 52 | 53 | 54 | 55 | 56 | ${quarkus.platform.group-id} 57 | quarkus-maven-plugin 58 | ${quarkus.platform.version} 59 | true 60 | 61 | 62 | 63 | build 64 | generate-code 65 | generate-code-tests 66 | 67 | 68 | 69 | 70 | 71 | maven-compiler-plugin 72 | ${compiler-plugin.version} 73 | 74 | 75 | -parameters 76 | 77 | 78 | 79 | 80 | maven-surefire-plugin 81 | ${surefire-plugin.version} 82 | 83 | 84 | org.jboss.logmanager.LogManager 85 | ${maven.home} 86 | 87 | 88 | 89 | 90 | maven-failsafe-plugin 91 | ${surefire-plugin.version} 92 | 93 | 94 | 95 | integration-test 96 | verify 97 | 98 | 99 | 100 | 101 | 102 | ${project.build.directory}/${project.build.finalName}-runner 103 | org.jboss.logmanager.LogManager 104 | ${maven.home} 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | native 114 | 115 | 116 | native 117 | 118 | 119 | 120 | false 121 | true 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/src/main/docker/Dockerfile.legacy-jar: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package -Dquarkus.package.jar.type=legacy-jar 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/quarkus-simple-application-legacy-jar . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/quarkus-simple-application-legacy-jar 15 | # 16 | # If you want to include the debug port into your docker image 17 | # you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005. 18 | # Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005 19 | # when running the container 20 | # 21 | # Then run the container using : 22 | # 23 | # docker run -i --rm -p 8080:8080 quarkus/quarkus-simple-application-legacy-jar 24 | # 25 | # This image uses the `run-java.sh` script to run the application. 26 | # This scripts computes the command line to execute your Java application, and 27 | # includes memory/GC tuning. 28 | # You can configure the behavior using the following environment properties: 29 | # - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") 30 | # - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options 31 | # in JAVA_OPTS (example: "-Dsome.property=foo") 32 | # - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is 33 | # used to calculate a default maximal heap memory based on a containers restriction. 34 | # If used in a container without any memory constraints for the container then this 35 | # option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio 36 | # of the container available memory as set here. The default is `50` which means 50% 37 | # of the available memory is used as an upper boundary. You can skip this mechanism by 38 | # setting this value to `0` in which case no `-Xmx` option is added. 39 | # - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This 40 | # is used to calculate a default initial heap memory based on the maximum heap memory. 41 | # If used in a container without any memory constraints for the container then this 42 | # option has no effect. If there is a memory constraint then `-Xms` is set to a ratio 43 | # of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx` 44 | # is used as the initial heap size. You can skip this mechanism by setting this value 45 | # to `0` in which case no `-Xms` option is added (example: "25") 46 | # - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS. 47 | # This is used to calculate the maximum value of the initial heap memory. If used in 48 | # a container without any memory constraints for the container then this option has 49 | # no effect. If there is a memory constraint then `-Xms` is limited to the value set 50 | # here. The default is 4096MB which means the calculated value of `-Xms` never will 51 | # be greater than 4096MB. The value of this variable is expressed in MB (example: "4096") 52 | # - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output 53 | # when things are happening. This option, if set to true, will set 54 | # `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true"). 55 | # - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example: 56 | # true"). 57 | # - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787"). 58 | # - CONTAINER_CORE_LIMIT: A calculated core limit as described in 59 | # https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2") 60 | # - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024"). 61 | # - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion. 62 | # (example: "20") 63 | # - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking. 64 | # (example: "40") 65 | # - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection. 66 | # (example: "4") 67 | # - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus 68 | # previous GC times. (example: "90") 69 | # - GC_METASPACE_SIZE: The initial metaspace size. (example: "20") 70 | # - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100") 71 | # - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should 72 | # contain the necessary JRE command-line options to specify the required GC, which 73 | # will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC). 74 | # - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080") 75 | # - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080") 76 | # - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be 77 | # accessed directly. (example: "foo.example.com,bar.example.com") 78 | # 79 | ### 80 | FROM registry.access.redhat.com/ubi8/openjdk-17:1.19 81 | 82 | ENV LANGUAGE='en_US:en' 83 | 84 | 85 | COPY target/lib/* /deployments/lib/ 86 | COPY target/*-runner.jar /deployments/quarkus-run.jar 87 | 88 | EXPOSE 8080 89 | USER 185 90 | ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" 91 | ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" 92 | 93 | ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] 94 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/src/main/docker/Dockerfile.native: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package -Dnative 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/quarkus-simple-application . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/quarkus-simple-application 15 | # 16 | ### 17 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.9 18 | WORKDIR /work/ 19 | RUN chown 1001 /work \ 20 | && chmod "g+rwX" /work \ 21 | && chown 1001:root /work 22 | COPY --chown=1001:root target/*-runner /work/application 23 | 24 | EXPOSE 8080 25 | USER 1001 26 | 27 | ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] 28 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/src/main/docker/Dockerfile.native-micro: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # It uses a micro base image, tuned for Quarkus native executables. 4 | # It reduces the size of the resulting container image. 5 | # Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. 6 | # 7 | # Before building the container image run: 8 | # 9 | # ./mvnw package -Dnative 10 | # 11 | # Then, build the image with: 12 | # 13 | # docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/quarkus-simple-application . 14 | # 15 | # Then run the container using: 16 | # 17 | # docker run -i --rm -p 8080:8080 quarkus/quarkus-simple-application 18 | # 19 | ### 20 | FROM quay.io/quarkus/quarkus-micro-image:2.0 21 | WORKDIR /work/ 22 | RUN chown 1001 /work \ 23 | && chmod "g+rwX" /work \ 24 | && chown 1001:root /work 25 | COPY --chown=1001:root target/*-runner /work/application 26 | 27 | EXPOSE 8080 28 | USER 1001 29 | 30 | ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] 31 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/src/main/java/com/example/GreetingResource.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import jakarta.ws.rs.GET; 4 | import jakarta.ws.rs.Path; 5 | import jakarta.ws.rs.Produces; 6 | import jakarta.ws.rs.core.MediaType; 7 | 8 | @Path("/hello") 9 | public class GreetingResource { 10 | 11 | @GET 12 | @Produces(MediaType.TEXT_PLAIN) 13 | public String hello() { 14 | return "Hello from Quarkus REST"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/src/main/resources/application.properties -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/src/test/java/com/example/GreetingResourceIT.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.quarkus.test.junit.QuarkusIntegrationTest; 4 | 5 | @QuarkusIntegrationTest 6 | class GreetingResourceIT extends GreetingResourceTest { 7 | // Execute the same tests but in packaged mode. 8 | } 9 | -------------------------------------------------------------------------------- /quarkus-micronaut/01-build-a-simple-java-application/quarkus-simple-application/src/test/java/com/example/GreetingResourceTest.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.quarkus.test.junit.QuarkusTest; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static io.restassured.RestAssured.given; 7 | import static org.hamcrest.CoreMatchers.is; 8 | 9 | @QuarkusTest 10 | class GreetingResourceTest { 11 | @Test 12 | void testHelloEndpoint() { 13 | given() 14 | .when().get("/hello") 15 | .then() 16 | .statusCode(200) 17 | .body(is("Hello from Quarkus REST")); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !target/*-runner 3 | !target/*-runner.jar 4 | !target/lib/* 5 | !target/quarkus-app/* -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/.gitignore: -------------------------------------------------------------------------------- 1 | #Maven 2 | target/ 3 | pom.xml.tag 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | release.properties 7 | .flattened-pom.xml 8 | 9 | # Eclipse 10 | .project 11 | .classpath 12 | .settings/ 13 | bin/ 14 | 15 | # IntelliJ 16 | .idea 17 | *.ipr 18 | *.iml 19 | *.iws 20 | 21 | # NetBeans 22 | nb-configuration.xml 23 | 24 | # Visual Studio Code 25 | .vscode 26 | .factorypath 27 | 28 | # OSX 29 | .DS_Store 30 | 31 | # Vim 32 | *.swp 33 | *.swo 34 | 35 | # patch 36 | *.orig 37 | *.rej 38 | 39 | # Local environment 40 | .env 41 | 42 | # Plugin directory 43 | /.quarkus/cli/plugins/ 44 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/.mvn/wrapper/.gitignore: -------------------------------------------------------------------------------- 1 | maven-wrapper.jar 2 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.net.Authenticator; 23 | import java.net.PasswordAuthentication; 24 | import java.net.URL; 25 | import java.nio.file.Files; 26 | import java.nio.file.Path; 27 | import java.nio.file.Paths; 28 | import java.nio.file.StandardCopyOption; 29 | 30 | public final class MavenWrapperDownloader 31 | { 32 | private static final String WRAPPER_VERSION = "3.2.0"; 33 | 34 | private static final boolean VERBOSE = Boolean.parseBoolean( System.getenv( "MVNW_VERBOSE" ) ); 35 | 36 | public static void main( String[] args ) 37 | { 38 | log( "Apache Maven Wrapper Downloader " + WRAPPER_VERSION ); 39 | 40 | if ( args.length != 2 ) 41 | { 42 | System.err.println( " - ERROR wrapperUrl or wrapperJarPath parameter missing" ); 43 | System.exit( 1 ); 44 | } 45 | 46 | try 47 | { 48 | log( " - Downloader started" ); 49 | final URL wrapperUrl = new URL( args[0] ); 50 | final String jarPath = args[1].replace( "..", "" ); // Sanitize path 51 | final Path wrapperJarPath = Paths.get( jarPath ).toAbsolutePath().normalize(); 52 | downloadFileFromURL( wrapperUrl, wrapperJarPath ); 53 | log( "Done" ); 54 | } 55 | catch ( IOException e ) 56 | { 57 | System.err.println( "- Error downloading: " + e.getMessage() ); 58 | if ( VERBOSE ) 59 | { 60 | e.printStackTrace(); 61 | } 62 | System.exit( 1 ); 63 | } 64 | } 65 | 66 | private static void downloadFileFromURL( URL wrapperUrl, Path wrapperJarPath ) 67 | throws IOException 68 | { 69 | log( " - Downloading to: " + wrapperJarPath ); 70 | if ( System.getenv( "MVNW_USERNAME" ) != null && System.getenv( "MVNW_PASSWORD" ) != null ) 71 | { 72 | final String username = System.getenv( "MVNW_USERNAME" ); 73 | final char[] password = System.getenv( "MVNW_PASSWORD" ).toCharArray(); 74 | Authenticator.setDefault( new Authenticator() 75 | { 76 | @Override 77 | protected PasswordAuthentication getPasswordAuthentication() 78 | { 79 | return new PasswordAuthentication( username, password ); 80 | } 81 | } ); 82 | } 83 | try ( InputStream inStream = wrapperUrl.openStream() ) 84 | { 85 | Files.copy( inStream, wrapperJarPath, StandardCopyOption.REPLACE_EXISTING ); 86 | } 87 | log( " - Downloader complete" ); 88 | } 89 | 90 | private static void log( String msg ) 91 | { 92 | if ( VERBOSE ) 93 | { 94 | System.out.println( msg ); 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip 18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 19 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/README.md: -------------------------------------------------------------------------------- 1 | # city-service 2 | 3 | This project uses Quarkus, the Supersonic Subatomic Java Framework. 4 | 5 | If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ . 6 | 7 | ## Running the application in dev mode 8 | 9 | You can run your application in dev mode that enables live coding using: 10 | ```shell script 11 | ./mvnw compile quarkus:dev 12 | ``` 13 | 14 | > **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/. 15 | 16 | ## Packaging and running the application 17 | 18 | The application can be packaged using: 19 | ```shell script 20 | ./mvnw package 21 | ``` 22 | It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory. 23 | Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory. 24 | 25 | The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`. 26 | 27 | If you want to build an _über-jar_, execute the following command: 28 | ```shell script 29 | ./mvnw package -Dquarkus.package.type=uber-jar 30 | ``` 31 | 32 | The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`. 33 | 34 | ## Creating a native executable 35 | 36 | You can create a native executable using: 37 | ```shell script 38 | ./mvnw package -Dnative 39 | ``` 40 | 41 | Or, if you don't have GraalVM installed, you can run the native executable build in a container using: 42 | ```shell script 43 | ./mvnw package -Dnative -Dquarkus.native.container-build=true 44 | ``` 45 | 46 | You can then execute your native executable with: `./target/city-service-0.0.1-SNAPSHOT-runner` 47 | 48 | If you want to learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling. 49 | 50 | ## Related Guides 51 | 52 | - MongoDB with Panache ([guide](https://quarkus.io/guides/mongodb-panache)): Simplify your persistence code for MongoDB via the active record or the repository pattern 53 | 54 | ## Provided Code 55 | 56 | ### RESTEasy Reactive 57 | 58 | Easily start your Reactive RESTful Web Services 59 | 60 | [Related guide section...](https://quarkus.io/guides/getting-started-reactive#reactive-jax-rs-resources) 61 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/src/main/docker/Dockerfile.legacy-jar: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package -Dquarkus.package.type=legacy-jar 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/city-service-legacy-jar . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/city-service-legacy-jar 15 | # 16 | # If you want to include the debug port into your docker image 17 | # you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005. 18 | # Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005 19 | # when running the container 20 | # 21 | # Then run the container using : 22 | # 23 | # docker run -i --rm -p 8080:8080 quarkus/city-service-legacy-jar 24 | # 25 | # This image uses the `run-java.sh` script to run the application. 26 | # This scripts computes the command line to execute your Java application, and 27 | # includes memory/GC tuning. 28 | # You can configure the behavior using the following environment properties: 29 | # - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") 30 | # - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options 31 | # in JAVA_OPTS (example: "-Dsome.property=foo") 32 | # - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is 33 | # used to calculate a default maximal heap memory based on a containers restriction. 34 | # If used in a container without any memory constraints for the container then this 35 | # option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio 36 | # of the container available memory as set here. The default is `50` which means 50% 37 | # of the available memory is used as an upper boundary. You can skip this mechanism by 38 | # setting this value to `0` in which case no `-Xmx` option is added. 39 | # - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This 40 | # is used to calculate a default initial heap memory based on the maximum heap memory. 41 | # If used in a container without any memory constraints for the container then this 42 | # option has no effect. If there is a memory constraint then `-Xms` is set to a ratio 43 | # of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx` 44 | # is used as the initial heap size. You can skip this mechanism by setting this value 45 | # to `0` in which case no `-Xms` option is added (example: "25") 46 | # - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS. 47 | # This is used to calculate the maximum value of the initial heap memory. If used in 48 | # a container without any memory constraints for the container then this option has 49 | # no effect. If there is a memory constraint then `-Xms` is limited to the value set 50 | # here. The default is 4096MB which means the calculated value of `-Xms` never will 51 | # be greater than 4096MB. The value of this variable is expressed in MB (example: "4096") 52 | # - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output 53 | # when things are happening. This option, if set to true, will set 54 | # `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true"). 55 | # - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example: 56 | # true"). 57 | # - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787"). 58 | # - CONTAINER_CORE_LIMIT: A calculated core limit as described in 59 | # https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2") 60 | # - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024"). 61 | # - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion. 62 | # (example: "20") 63 | # - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking. 64 | # (example: "40") 65 | # - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection. 66 | # (example: "4") 67 | # - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus 68 | # previous GC times. (example: "90") 69 | # - GC_METASPACE_SIZE: The initial metaspace size. (example: "20") 70 | # - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100") 71 | # - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should 72 | # contain the necessary JRE command-line options to specify the required GC, which 73 | # will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC). 74 | # - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080") 75 | # - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080") 76 | # - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be 77 | # accessed directly. (example: "foo.example.com,bar.example.com") 78 | # 79 | ### 80 | FROM registry.access.redhat.com/ubi8/openjdk-17:1.18 81 | 82 | ENV LANGUAGE='en_US:en' 83 | 84 | 85 | COPY target/lib/* /deployments/lib/ 86 | COPY target/*-runner.jar /deployments/quarkus-run.jar 87 | 88 | EXPOSE 8080 89 | USER 185 90 | ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" 91 | ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" 92 | 93 | ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] 94 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/src/main/docker/Dockerfile.native: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package -Dnative 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/city-service . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/city-service 15 | # 16 | ### 17 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.9 18 | WORKDIR /work/ 19 | RUN chown 1001 /work \ 20 | && chmod "g+rwX" /work \ 21 | && chown 1001:root /work 22 | COPY --chown=1001:root target/*-runner /work/application 23 | 24 | EXPOSE 8080 25 | USER 1001 26 | 27 | ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] 28 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/src/main/docker/Dockerfile.native-micro: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # It uses a micro base image, tuned for Quarkus native executables. 4 | # It reduces the size of the resulting container image. 5 | # Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. 6 | # 7 | # Before building the container image run: 8 | # 9 | # ./mvnw package -Dnative 10 | # 11 | # Then, build the image with: 12 | # 13 | # docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/city-service . 14 | # 15 | # Then run the container using: 16 | # 17 | # docker run -i --rm -p 8080:8080 quarkus/city-service 18 | # 19 | ### 20 | FROM quay.io/quarkus/quarkus-micro-image:2.0 21 | WORKDIR /work/ 22 | RUN chown 1001 /work \ 23 | && chmod "g+rwX" /work \ 24 | && chown 1001:root /work 25 | COPY --chown=1001:root target/*-runner /work/application 26 | 27 | EXPOSE 8080 28 | USER 1001 29 | 30 | ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] 31 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/src/main/java/com/example/City.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.quarkus.hibernate.reactive.panache.PanacheEntity; 4 | 5 | import jakarta.persistence.*; 6 | 7 | @Entity 8 | public class City extends PanacheEntity { 9 | 10 | @Column(unique = true) 11 | public String name; 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public void setName(String name) { 18 | this.name = name; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/src/main/java/com/example/CityResource.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.quarkus.logging.Log; 4 | import io.smallrye.mutiny.Uni; 5 | import jakarta.ws.rs.*; 6 | import jakarta.ws.rs.core.MediaType; 7 | 8 | import java.util.List; 9 | 10 | @Path("/") 11 | public class CityResource { 12 | 13 | @GET 14 | @Path("cities") 15 | @Produces(MediaType.APPLICATION_JSON) 16 | public Uni> getCities() { 17 | Log.info("Getting all cities"); 18 | return City.listAll(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | quarkus.liquibase.migrate-at-start=true 2 | 3 | # OpenTelemetry configurations 4 | quarkus.otel.exporter.otlp.traces.endpoint=${OTEL_EXPORTER_OTLP_ENDPOINT} 5 | quarkus.datasource.jdbc.telemetry=true 6 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/src/main/resources/db/changeLog.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/src/test/java/com/example/CityResourceIT.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.quarkus.test.junit.QuarkusIntegrationTest; 4 | 5 | @QuarkusIntegrationTest 6 | class CityResourceIT extends CityResourceTest { 7 | // Execute the same tests but in packaged mode. 8 | } 9 | -------------------------------------------------------------------------------- /quarkus-micronaut/02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/city-service/src/test/java/com/example/CityResourceTest.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.quarkus.test.junit.QuarkusTest; 4 | import org.junit.jupiter.api.Test; 5 | 6 | @QuarkusTest 7 | class CityResourceTest { 8 | @Test 9 | void testQuarkusContextLoads() { 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/.gitignore: -------------------------------------------------------------------------------- 1 | Thumbs.db 2 | .DS_Store 3 | .gradle 4 | build/ 5 | target/ 6 | out/ 7 | .micronaut/ 8 | .idea 9 | *.iml 10 | *.ipr 11 | *.iws 12 | .project 13 | .settings 14 | .classpath 15 | .factorypath 16 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip 18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar 19 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/Dockerfile-otel-agent: -------------------------------------------------------------------------------- 1 | FROM openjdk:17 2 | 3 | WORKDIR /app 4 | 5 | ADD https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar /app/opentelemetry-javaagent.jar 6 | 7 | COPY target/weather-service-0.1.jar /app/weather-service.jar 8 | 9 | EXPOSE 8080 10 | 11 | CMD ["java", "-javaagent:/app/opentelemetry-javaagent.jar", "-jar", "weather-service.jar"] -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/README.md: -------------------------------------------------------------------------------- 1 | ## Micronaut 4.3.2 Documentation 2 | 3 | - [User Guide](https://docs.micronaut.io/4.3.2/guide/index.html) 4 | - [API Reference](https://docs.micronaut.io/4.3.2/api/index.html) 5 | - [Configuration Reference](https://docs.micronaut.io/4.3.2/guide/configurationreference.html) 6 | - [Micronaut Guides](https://guides.micronaut.io/index.html) 7 | --- 8 | 9 | - [Micronaut Maven Plugin documentation](https://micronaut-projects.github.io/micronaut-maven-plugin/latest/) 10 | ## Feature micronaut-aot documentation 11 | 12 | - [Micronaut AOT documentation](https://micronaut-projects.github.io/micronaut-aot/latest/guide/) 13 | 14 | 15 | ## Feature data-jdbc documentation 16 | 17 | - [Micronaut Data JDBC documentation](https://micronaut-projects.github.io/micronaut-data/latest/guide/index.html#jdbc) 18 | 19 | 20 | ## Feature validation documentation 21 | 22 | - [Micronaut Validation documentation](https://micronaut-projects.github.io/micronaut-validation/latest/guide/) 23 | 24 | 25 | ## Feature test-resources documentation 26 | 27 | - [Micronaut Test Resources documentation](https://micronaut-projects.github.io/micronaut-test-resources/latest/guide/) 28 | 29 | 30 | ## Feature jdbc-hikari documentation 31 | 32 | - [Micronaut Hikari JDBC Connection Pool documentation](https://micronaut-projects.github.io/micronaut-sql/latest/guide/index.html#jdbc) 33 | 34 | 35 | ## Feature maven-enforcer-plugin documentation 36 | 37 | - [https://maven.apache.org/enforcer/maven-enforcer-plugin/](https://maven.apache.org/enforcer/maven-enforcer-plugin/) 38 | 39 | 40 | ## Feature flyway documentation 41 | 42 | - [Micronaut Flyway Database Migration documentation](https://micronaut-projects.github.io/micronaut-flyway/latest/guide/index.html) 43 | 44 | - [https://flywaydb.org/](https://flywaydb.org/) 45 | 46 | 47 | ## Feature serialization-jackson documentation 48 | 49 | - [Micronaut Serialization Jackson Core documentation](https://micronaut-projects.github.io/micronaut-serialization/latest/guide/) 50 | 51 | 52 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/aot-jar.properties: -------------------------------------------------------------------------------- 1 | # AOT configuration properties for jar packaging 2 | # Please review carefully the optimizations enabled below 3 | # Check https://micronaut-projects.github.io/micronaut-aot/latest/guide/ for more details 4 | 5 | # Caches environment property values: environment properties will be deemed immutable after application startup. 6 | cached.environment.enabled=true 7 | 8 | # Precomputes Micronaut configuration property keys from the current environment variables 9 | precompute.environment.properties.enabled=true 10 | 11 | # Converts YAML configuration files to Java configuration 12 | yaml.to.java.config.enabled=true 13 | 14 | # Scans for service types ahead-of-time, avoiding classpath scanning at startup 15 | serviceloading.jit.enabled=true 16 | 17 | # Scans reactive types at build time instead of runtime 18 | scan.reactive.types.enabled=true 19 | 20 | # Deduces the environment at build time instead of runtime 21 | deduce.environment.enabled=true 22 | 23 | # Checks of existence of some types at build time instead of runtime 24 | known.missing.types.enabled=true 25 | 26 | # Precomputes property sources at build time 27 | sealed.property.source.enabled=true 28 | 29 | # The list of service types to be scanned (comma separated) 30 | service.types=io.micronaut.context.env.PropertySourceLoader,io.micronaut.inject.BeanConfiguration,io.micronaut.inject.BeanDefinitionReference,io.micronaut.http.HttpRequestFactory,io.micronaut.http.HttpResponseFactory,io.micronaut.core.beans.BeanIntrospectionReference,io.micronaut.core.convert.TypeConverterRegistrar,io.micronaut.context.env.PropertyExpressionResolver 31 | 32 | # A list of types that the AOT analyzer needs to check for existence (comma separated) 33 | known.missing.types.list=io.reactivex.Observable,reactor.core.publisher.Flux,kotlinx.coroutines.flow.Flow,io.reactivex.rxjava3.core.Flowable,io.reactivex.rxjava3.core.Observable,io.reactivex.Single,reactor.core.publisher.Mono,io.reactivex.Maybe,io.reactivex.rxjava3.core.Single,io.reactivex.rxjava3.core.Maybe,io.reactivex.Completable,io.reactivex.rxjava3.core.Completable,io.methvin.watchservice.MacOSXListeningWatchService,io.micronaut.core.async.publisher.CompletableFuturePublisher,io.micronaut.core.async.publisher.Publishers.JustPublisher,io.micronaut.core.async.subscriber.Completable 34 | 35 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/aot-native-image.properties: -------------------------------------------------------------------------------- 1 | # AOT configuration properties for native-image packaging 2 | # Please review carefully the optimizations enabled below 3 | # Check https://micronaut-projects.github.io/micronaut-aot/latest/guide/ for more details 4 | 5 | # Caches environment property values: environment properties will be deemed immutable after application startup. 6 | cached.environment.enabled=true 7 | 8 | # Precomputes Micronaut configuration property keys from the current environment variables 9 | precompute.environment.properties.enabled=true 10 | 11 | # Converts YAML configuration files to Java configuration 12 | yaml.to.java.config.enabled=false 13 | 14 | # Generates GraalVM configuration files required to load the AOT optimizations 15 | graalvm.config.enabled=true 16 | 17 | # Scans for service types ahead-of-time, avoiding classpath scanning at startup 18 | serviceloading.native.enabled=false 19 | 20 | # Scans reactive types at build time instead of runtime 21 | scan.reactive.types.enabled=true 22 | 23 | # Deduces the environment at build time instead of runtime 24 | deduce.environment.enabled=true 25 | 26 | # Checks of existence of some types at build time instead of runtime 27 | known.missing.types.enabled=true 28 | 29 | # Precomputes property sources at build time 30 | sealed.property.source.enabled=true 31 | 32 | # The list of service types to be scanned (comma separated) 33 | service.types=io.micronaut.context.env.PropertySourceLoader,io.micronaut.inject.BeanConfiguration,io.micronaut.inject.BeanDefinitionReference,io.micronaut.http.HttpRequestFactory,io.micronaut.http.HttpResponseFactory,io.micronaut.core.beans.BeanIntrospectionReference,io.micronaut.core.convert.TypeConverterRegistrar,io.micronaut.context.env.PropertyExpressionResolver 34 | 35 | # A list of types that the AOT analyzer needs to check for existence (comma separated) 36 | known.missing.types.list=io.reactivex.Observable,reactor.core.publisher.Flux,kotlinx.coroutines.flow.Flow,io.reactivex.rxjava3.core.Flowable,io.reactivex.rxjava3.core.Observable,io.reactivex.Single,reactor.core.publisher.Mono,io.reactivex.Maybe,io.reactivex.rxjava3.core.Single,io.reactivex.rxjava3.core.Maybe,io.reactivex.Completable,io.reactivex.rxjava3.core.Completable,io.methvin.watchservice.MacOSXListeningWatchService,io.micronaut.core.async.publisher.CompletableFuturePublisher,io.micronaut.core.async.publisher.Publishers.JustPublisher,io.micronaut.core.async.subscriber.Completable 37 | 38 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/micronaut-cli.yml: -------------------------------------------------------------------------------- 1 | applicationType: default 2 | defaultPackage: com.example 3 | testFramework: junit 4 | sourceLanguage: java 5 | buildTool: maven 6 | features: [app-name, data, data-jdbc, flyway, graalvm, http-client-test, java, java-application, jdbc-hikari, junit, logback, maven, maven-enforcer-plugin, micronaut-aot, micronaut-http-validation, mysql, netty-server, properties, readme, serialization-jackson, shade, static-resources, test-resources, validation] 7 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/src/main/java/com/example/Application.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.micronaut.context.annotation.Factory; 4 | import io.micronaut.runtime.Micronaut; 5 | 6 | @Factory 7 | public class Application { 8 | 9 | public static void main(String[] args) { 10 | Micronaut.run(Application.class, args); 11 | } 12 | } -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/src/main/java/com/example/WeatherController.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import com.example.domain.Weather; 4 | import io.micronaut.http.annotation.Controller; 5 | import io.micronaut.http.annotation.Get; 6 | import io.micronaut.http.annotation.QueryValue; 7 | import io.micronaut.scheduling.TaskExecutors; 8 | import io.micronaut.scheduling.annotation.ExecuteOn; 9 | 10 | import jakarta.validation.constraints.NotBlank; 11 | import java.util.Optional; 12 | 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | @ExecuteOn(TaskExecutors.BLOCKING) 17 | @Controller("/weather") 18 | public class WeatherController { 19 | 20 | private static Logger logger = LoggerFactory.getLogger(WeatherController.class); 21 | 22 | protected final WeatherRepository weatherRepository; 23 | 24 | public WeatherController(WeatherRepository weatherRepository) { 25 | this.weatherRepository = weatherRepository; 26 | } 27 | 28 | @Get("/city") 29 | public Optional show(@QueryValue("name") @NotBlank String cityName) { 30 | logger.info("Getting weather for city: " + cityName); 31 | return weatherRepository.findById(cityName); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/src/main/java/com/example/WeatherRepository.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import com.example.domain.Weather; 4 | import io.micronaut.data.jdbc.annotation.JdbcRepository; 5 | import io.micronaut.data.model.query.builder.sql.Dialect; 6 | import io.micronaut.data.repository.CrudRepository; 7 | 8 | @JdbcRepository(dialect = Dialect.MYSQL) 9 | public interface WeatherRepository extends CrudRepository { 10 | } 11 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/src/main/java/com/example/domain/Weather.java: -------------------------------------------------------------------------------- 1 | package com.example.domain; 2 | 3 | import io.micronaut.data.annotation.Id; 4 | import io.micronaut.data.annotation.MappedEntity; 5 | import io.micronaut.serde.annotation.Serdeable; 6 | 7 | import jakarta.validation.constraints.NotNull; 8 | 9 | @Serdeable 10 | @MappedEntity 11 | public class Weather { 12 | 13 | @Id 14 | private String city; 15 | 16 | @NotNull 17 | private String description; 18 | 19 | @NotNull 20 | private String icon; 21 | 22 | public String getCity() { 23 | return city; 24 | } 25 | 26 | public void setCity(String city) { 27 | this.city = city; 28 | } 29 | 30 | public String getDescription() { 31 | return description; 32 | } 33 | 34 | public void setDescription(String description) { 35 | this.description = description; 36 | } 37 | 38 | public String getIcon() { 39 | return icon; 40 | } 41 | 42 | public void setIcon(String icon) { 43 | this.icon = icon; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "Weather{" + 49 | "city=" + city + 50 | ", description='" + description + '\'' + 51 | ", icon='" + icon + '\'' + 52 | '}'; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | flyway.datasources.default.enabled=true 2 | datasources.default.db-type=mysql 3 | datasources.default.dialect=MYSQL 4 | micronaut.application.name=weather-service 5 | datasources.default.driver-class-name=com.mysql.cj.jdbc.Driver 6 | 7 | # OpenTelemetry configurations 8 | otel.traces.exporter=otlp 9 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/src/main/resources/db/migration/V1__schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS weather; 2 | 3 | CREATE TABLE weather ( 4 | city VARCHAR(255) NOT NULL UNIQUE PRIMARY KEY, 5 | description VARCHAR(255) NOT NULL, 6 | icon VARCHAR(255) NOT NULL 7 | ); 8 | 9 | INSERT INTO weather (city, description, icon) VALUES ('Paris, France', 'Very cloudy!', 'weather-fog'); 10 | INSERT INTO weather (city, description, icon) VALUES ('London, UK', 'Quite cloudy', 'weather-pouring'); 11 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /quarkus-micronaut/03-build-a-micronaut-microservice-using-mysql/weather-service/src/test/java/com/example/WeatherServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.micronaut.runtime.EmbeddedApplication; 4 | import io.micronaut.test.extensions.junit5.annotation.MicronautTest; 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.Assertions; 7 | 8 | import jakarta.inject.Inject; 9 | 10 | @MicronautTest 11 | class WeatherServiceTest { 12 | 13 | @Inject 14 | EmbeddedApplication application; 15 | 16 | @Test 17 | void testItWorks() { 18 | Assertions.assertTrue(application.isRunning()); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /quarkus-micronaut/04-build-a-nginx-reverse-proxy/gateway/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG NGINX_VERSION=1.26 2 | FROM nginx:$NGINX_VERSION-otel 3 | 4 | COPY nginx/nginx.conf.template /etc/nginx/nginx.conf.template 5 | COPY nginx/entrypoint.sh / 6 | 7 | ENV OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 8 | ENV PORT=8080 9 | ENV CITY_SERVICE_URL=http://city-service:8080 10 | ENV WEATHER_SERVICE_URL=http://weather-service:8080 11 | ENTRYPOINT ["/entrypoint.sh"] 12 | CMD ["nginx", "-g", "daemon off;"] 13 | -------------------------------------------------------------------------------- /quarkus-micronaut/04-build-a-nginx-reverse-proxy/gateway/nginx/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | set -eu 3 | 4 | # Remove starting http:// from the OTEL_EXPORTER_OTLP_ENDPOINT, see https://github.com/grpc/grpc/issues/19954#issuecomment-676273319 5 | export OTEL_EXPORTER_OTLP_ENDPOINT=$(echo $OTEL_EXPORTER_OTLP_ENDPOINT | sed 's/http:\/\///g') 6 | 7 | # Replace the environment variables in the nginx.conf.template with the actual values 8 | envsubst '${OTEL_EXPORTER_OTLP_ENDPOINT} ${PORT} ${CITY_SERVICE_URL} ${WEATHER_SERVICE_URL}' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf 9 | 10 | exec "$@" 11 | -------------------------------------------------------------------------------- /quarkus-micronaut/04-build-a-nginx-reverse-proxy/gateway/nginx/nginx.conf.template: -------------------------------------------------------------------------------- 1 | # Load the OpenTelemetry module 2 | load_module modules/ngx_otel_module.so; 3 | 4 | events {} 5 | 6 | http { 7 | 8 | # Turn tracing on for http traffic 9 | otel_trace on; 10 | 11 | # If you are at the start of the request, this context 12 | # will be created by the library and consumed by downstream 13 | # services. Required if you want traces to be connected to each 14 | # other across services ("distributed tracing") 15 | otel_trace_context inject; 16 | 17 | # This is how the NGINX server will appear in your trace viewer 18 | otel_service_name "gateway"; 19 | 20 | otel_exporter { 21 | endpoint ${OTEL_EXPORTER_OTLP_ENDPOINT}; 22 | } 23 | 24 | server { 25 | # Server configuration 26 | listen ${PORT}; 27 | # Allow CORS 28 | add_header 'Access-Control-Allow-Origin' '*'; 29 | 30 | # Route requests /city-service to the city-service defined in the environment variable CITY_SERVICE_URL 31 | location /city-service { 32 | rewrite ^/city-service/(.*)$ /$1 break; 33 | 34 | proxy_pass ${CITY_SERVICE_URL}; 35 | proxy_http_version 1.1; 36 | } 37 | 38 | # Route requests /weather-service to the weather-service defined in the environment variable WEATHER_SERVICE_URL 39 | location /weather-service { 40 | rewrite ^/weather-service/(.*)$ /$1 break; 41 | 42 | proxy_pass ${WEATHER_SERVICE_URL}; 43 | proxy_http_version 1.1; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/media/01-vuejs-frontend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/media/01-vuejs-frontend.png -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | not ie 11 5 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/Dockerfile: -------------------------------------------------------------------------------- 1 | # build stage 2 | FROM node:23 AS build-stage 3 | WORKDIR /app 4 | COPY package*.json ./ 5 | RUN npm install 6 | COPY . . 7 | RUN npm run build 8 | 9 | # production stage 10 | FROM nginx:stable-alpine AS production-stage 11 | COPY --from=build-stage /app/dist /usr/share/nginx/html 12 | COPY ./docker/entrypoint.sh /entrypoint.sh 13 | RUN chmod +x /entrypoint.sh 14 | EXPOSE 80 15 | ENV GATEWAY_NAME=gateway 16 | ENTRYPOINT ["/entrypoint.sh"] 17 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/README.md: -------------------------------------------------------------------------------- 1 | # Vuetify (Default) 2 | 3 | This is the official scaffolding tool for Vuetify, designed to give you a head start in building your new Vuetify application. It sets up a base template with all the necessary configurations and standard directory structure, enabling you to begin development without the hassle of setting up the project from scratch. 4 | 5 | ## ❗️ Important Links 6 | 7 | - 📄 [Docs](https://vuetifyjs.com/) 8 | - 🚨 [Issues](https://issues.vuetifyjs.com/) 9 | - 🏬 [Store](https://store.vuetifyjs.com/) 10 | - 🎮 [Playground](https://play.vuetifyjs.com/) 11 | - 💬 [Discord](https://community.vuetifyjs.com) 12 | 13 | ## 💿 Install 14 | 15 | Set up your project using your preferred package manager. Use the corresponding command to install the dependencies: 16 | 17 | | Package Manager | Command | 18 | |---------------------------------------------------------------|----------------| 19 | | [yarn](https://yarnpkg.com/getting-started) | `yarn install` | 20 | | [npm](https://docs.npmjs.com/cli/v7/commands/npm-install) | `npm install` | 21 | | [pnpm](https://pnpm.io/installation) | `pnpm install` | 22 | | [bun](https://bun.sh/#getting-started) | `bun install` | 23 | 24 | After completing the installation, your environment is ready for Vuetify development. 25 | 26 | ## ✨ Features 27 | 28 | - 🖼️ **Optimized Front-End Stack**: Leverage the latest Vue 3 and Vuetify 3 for a modern, reactive UI development experience. [Vue 3](https://v3.vuejs.org/) | [Vuetify 3](https://vuetifyjs.com/en/) 29 | - 🗃️ **State Management**: Integrated with [Pinia](https://pinia.vuejs.org/), the intuitive, modular state management solution for Vue. 30 | - 🚦 **Routing and Layouts**: Utilizes Vue Router for SPA navigation and vite-plugin-vue-layouts for organizing Vue file layouts. [Vue Router](https://router.vuejs.org/) | [vite-plugin-vue-layouts](https://github.com/JohnCampionJr/vite-plugin-vue-layouts) 31 | - ⚡ **Next-Gen Tooling**: Powered by Vite, experience fast cold starts and instant HMR (Hot Module Replacement). [Vite](https://vitejs.dev/) 32 | - 🧩 **Automated Component Importing**: Streamline your workflow with unplugin-vue-components, automatically importing components as you use them. [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components) 33 | 34 | These features are curated to provide a seamless development experience from setup to deployment, ensuring that your Vuetify application is both powerful and maintainable. 35 | 36 | ## 💡 Usage 37 | 38 | This section covers how to start the development server and build your project for production. 39 | 40 | ### Starting the Development Server 41 | 42 | To start the development server with hot-reload, run the following command. The server will be accessible at [http://localhost:3000](http://localhost:3000): 43 | 44 | ```bash 45 | yarn dev 46 | ``` 47 | 48 | (Repeat for npm, pnpm, and bun with respective commands.) 49 | 50 | > Add NODE_OPTIONS='--no-warnings' to suppress the JSON import warnings that happen as part of the Vuetify import mapping. If you are on Node [v21.3.0](https://nodejs.org/en/blog/release/v21.3.0) or higher, you can change this to NODE_OPTIONS='--disable-warning=5401'. If you don't mind the warning, you can remove this from your package.json dev script. 51 | 52 | ### Building for Production 53 | 54 | To build your project for production, use: 55 | 56 | ```bash 57 | yarn build 58 | ``` 59 | 60 | (Repeat for npm, pnpm, and bun with respective commands.) 61 | 62 | Once the build process is completed, your application will be ready for deployment in a production environment. 63 | 64 | ## 💪 Support Vuetify Development 65 | 66 | This project is built with [Vuetify](https://vuetifyjs.com/en/), a UI Library with a comprehensive collection of Vue components. Vuetify is an MIT licensed Open Source project that has been made possible due to the generous contributions by our [sponsors and backers](https://vuetifyjs.com/introduction/sponsors-and-backers/). If you are interested in supporting this project, please consider: 67 | 68 | - [Requesting Enterprise Support](https://support.vuetifyjs.com/) 69 | - [Sponsoring John on Github](https://github.com/users/johnleider/sponsorship) 70 | - [Sponsoring Kael on Github](https://github.com/users/kaelwd/sponsorship) 71 | - [Supporting the team on Open Collective](https://opencollective.com/vuetify) 72 | - [Becoming a sponsor on Patreon](https://www.patreon.com/vuetify) 73 | - [Becoming a subscriber on Tidelift](https://tidelift.com/subscription/npm/vuetify) 74 | - [Making a one-time donation with Paypal](https://paypal.me/vuetify) 75 | 76 | ## 📑 License 77 | [MIT](http://opensource.org/licenses/MIT) 78 | 79 | Copyright (c) 2016-present Vuetify, LLC 80 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/docker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ROOT_DIR=/usr/share/nginx/html 4 | 5 | # Replace env vars in JavaScript files 6 | echo "Replacing env constants in JS" 7 | for file in $ROOT_DIR/assets/*.js; 8 | do 9 | echo "Processing $file ..."; 10 | sed -i 's|CONTAINER_APP_ENV_DNS_SUFFIX|'${CONTAINER_APP_ENV_DNS_SUFFIX}'|g' $file 11 | sed -i 's|GATEWAY_NAME|'${GATEWAY_NAME}'|g' $file 12 | done 13 | 14 | echo "Starting Nginx" 15 | nginx -g 'daemon off;' -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import globals from "globals"; 2 | import pluginJs from "@eslint/js"; 3 | import pluginVue from "eslint-plugin-vue"; 4 | 5 | 6 | export default [ 7 | {files: ["**/*.{js,mjs,cjs,vue}"]}, 8 | {languageOptions: { globals: globals.browser }}, 9 | pluginJs.configs.recommended, 10 | ...pluginVue.configs["flat/essential"], 11 | ]; -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | What's the weather today? 12 | 13 | 14 | 15 | 18 |
19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "target": "es5", 5 | "module": "esnext", 6 | "baseUrl": "./", 7 | "moduleResolution": "bundler", 8 | "paths": { 9 | "@/*": [ 10 | "src/*" 11 | ] 12 | }, 13 | "lib": [ 14 | "esnext", 15 | "dom", 16 | "dom.iterable", 17 | "scripthost" 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weather-app", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vite build", 7 | "preview": "vite preview" 8 | }, 9 | "dependencies": { 10 | "@mdi/font": "7.4.47", 11 | "roboto-fontface": "*", 12 | "vue": "^3.4.31", 13 | "vuetify": "^3.6.11" 14 | }, 15 | "devDependencies": { 16 | "@eslint/js": "^9.13.0", 17 | "@vitejs/plugin-vue": "^5.0.5", 18 | "eslint": "^9.13.0", 19 | "eslint-plugin-vue": "^9.29.1", 20 | "globals": "^15.11.0", 21 | "sass": "1.77.6", 22 | "unplugin-fonts": "^1.1.1", 23 | "unplugin-vue-components": "^0.27.2", 24 | "vite": "^5.3.3", 25 | "vite-plugin-vuetify": "^2.0.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/public/favicon.ico -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/src/App.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 49 | 50 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/src/components/WeatherComponent.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 86 | 87 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/src/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * main.js 3 | * 4 | * Bootstraps Vuetify and other plugins then mounts the App` 5 | */ 6 | 7 | // Plugins 8 | import { registerPlugins } from '@/plugins' 9 | 10 | // Components 11 | import App from './App.vue' 12 | 13 | // Composables 14 | import { createApp } from 'vue' 15 | 16 | const app = createApp(App) 17 | 18 | registerPlugins(app) 19 | 20 | app.mount('#app') 21 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/src/plugins/README.md: -------------------------------------------------------------------------------- 1 | # Plugins 2 | 3 | Plugins are a way to extend the functionality of your Vue application. Use this folder for registering plugins that you want to use globally. 4 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/src/plugins/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * plugins/index.js 3 | * 4 | * Automatically included in `./src/main.js` 5 | */ 6 | 7 | // Plugins 8 | import vuetify from './vuetify' 9 | 10 | export function registerPlugins (app) { 11 | app.use(vuetify) 12 | } 13 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/src/plugins/vuetify.js: -------------------------------------------------------------------------------- 1 | /** 2 | * plugins/vuetify.js 3 | * 4 | * Framework documentation: https://vuetifyjs.com` 5 | */ 6 | 7 | // Styles 8 | import '@mdi/font/css/materialdesignicons.css' 9 | import 'vuetify/styles' 10 | 11 | // Composables 12 | import { createVuetify } from 'vuetify' 13 | 14 | // https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides 15 | export default createVuetify({ 16 | theme: { 17 | defaultTheme: 'light', 18 | }, 19 | }) 20 | -------------------------------------------------------------------------------- /quarkus-micronaut/05-putting-it-all-together-a-complete-microservice-stack/weather-app/vite.config.mjs: -------------------------------------------------------------------------------- 1 | // Plugins 2 | import Components from 'unplugin-vue-components/vite' 3 | import Vue from '@vitejs/plugin-vue' 4 | import Vuetify, { transformAssetUrls } from 'vite-plugin-vuetify' 5 | import ViteFonts from 'unplugin-fonts/vite' 6 | 7 | // Utilities 8 | import { defineConfig } from 'vite' 9 | import { fileURLToPath, URL } from 'node:url' 10 | 11 | // https://vitejs.dev/config/ 12 | export default defineConfig({ 13 | plugins: [ 14 | Vue({ 15 | template: { transformAssetUrls } 16 | }), 17 | // https://github.com/vuetifyjs/vuetify-loader/tree/master/packages/vite-plugin#readme 18 | Vuetify(), 19 | Components(), 20 | ViteFonts({ 21 | google: { 22 | families: [{ 23 | name: 'Roboto', 24 | styles: 'wght@100;300;400;500;700;900', 25 | }], 26 | }, 27 | }), 28 | ], 29 | define: { 'process.env': {} }, 30 | resolve: { 31 | alias: { 32 | '@': fileURLToPath(new URL('./src', import.meta.url)) 33 | }, 34 | extensions: [ 35 | '.js', 36 | '.json', 37 | '.jsx', 38 | '.mjs', 39 | '.ts', 40 | '.tsx', 41 | '.vue', 42 | ], 43 | }, 44 | server: { 45 | port: 3000, 46 | }, 47 | }) 48 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !target/*-runner 3 | !target/*-runner.jar 4 | !target/lib/* 5 | !target/quarkus-app/* -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/.gitignore: -------------------------------------------------------------------------------- 1 | #Maven 2 | target/ 3 | pom.xml.tag 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | release.properties 7 | .flattened-pom.xml 8 | 9 | # Eclipse 10 | .project 11 | .classpath 12 | .settings/ 13 | bin/ 14 | 15 | # IntelliJ 16 | .idea 17 | *.ipr 18 | *.iml 19 | *.iws 20 | 21 | # NetBeans 22 | nb-configuration.xml 23 | 24 | # Visual Studio Code 25 | .vscode 26 | .factorypath 27 | 28 | # OSX 29 | .DS_Store 30 | 31 | # Vim 32 | *.swp 33 | *.swo 34 | 35 | # patch 36 | *.orig 37 | *.rej 38 | 39 | # Local environment 40 | .env 41 | 42 | # Plugin directory 43 | /.quarkus/cli/plugins/ 44 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/.mvn/wrapper/.gitignore: -------------------------------------------------------------------------------- 1 | maven-wrapper.jar 2 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.net.Authenticator; 23 | import java.net.PasswordAuthentication; 24 | import java.net.URL; 25 | import java.nio.file.Files; 26 | import java.nio.file.Path; 27 | import java.nio.file.Paths; 28 | import java.nio.file.StandardCopyOption; 29 | 30 | public final class MavenWrapperDownloader 31 | { 32 | private static final String WRAPPER_VERSION = "3.2.0"; 33 | 34 | private static final boolean VERBOSE = Boolean.parseBoolean( System.getenv( "MVNW_VERBOSE" ) ); 35 | 36 | public static void main( String[] args ) 37 | { 38 | log( "Apache Maven Wrapper Downloader " + WRAPPER_VERSION ); 39 | 40 | if ( args.length != 2 ) 41 | { 42 | System.err.println( " - ERROR wrapperUrl or wrapperJarPath parameter missing" ); 43 | System.exit( 1 ); 44 | } 45 | 46 | try 47 | { 48 | log( " - Downloader started" ); 49 | final URL wrapperUrl = new URL( args[0] ); 50 | final String jarPath = args[1].replace( "..", "" ); // Sanitize path 51 | final Path wrapperJarPath = Paths.get( jarPath ).toAbsolutePath().normalize(); 52 | downloadFileFromURL( wrapperUrl, wrapperJarPath ); 53 | log( "Done" ); 54 | } 55 | catch ( IOException e ) 56 | { 57 | System.err.println( "- Error downloading: " + e.getMessage() ); 58 | if ( VERBOSE ) 59 | { 60 | e.printStackTrace(); 61 | } 62 | System.exit( 1 ); 63 | } 64 | } 65 | 66 | private static void downloadFileFromURL( URL wrapperUrl, Path wrapperJarPath ) 67 | throws IOException 68 | { 69 | log( " - Downloading to: " + wrapperJarPath ); 70 | if ( System.getenv( "MVNW_USERNAME" ) != null && System.getenv( "MVNW_PASSWORD" ) != null ) 71 | { 72 | final String username = System.getenv( "MVNW_USERNAME" ); 73 | final char[] password = System.getenv( "MVNW_PASSWORD" ).toCharArray(); 74 | Authenticator.setDefault( new Authenticator() 75 | { 76 | @Override 77 | protected PasswordAuthentication getPasswordAuthentication() 78 | { 79 | return new PasswordAuthentication( username, password ); 80 | } 81 | } ); 82 | } 83 | try ( InputStream inStream = wrapperUrl.openStream() ) 84 | { 85 | Files.copy( inStream, wrapperJarPath, StandardCopyOption.REPLACE_EXISTING ); 86 | } 87 | log( " - Downloader complete" ); 88 | } 89 | 90 | private static void log( String msg ) 91 | { 92 | if ( VERBOSE ) 93 | { 94 | System.out.println( msg ); 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip 18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 19 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/README.md: -------------------------------------------------------------------------------- 1 | # ai-weather-application 2 | 3 | This project uses Quarkus, the Supersonic Subatomic Java Framework. 4 | 5 | If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ . 6 | 7 | ## Running the application in dev mode 8 | 9 | You can run your application in dev mode that enables live coding using: 10 | ```shell script 11 | ./mvnw compile quarkus:dev 12 | ``` 13 | 14 | > **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/. 15 | 16 | ## Packaging and running the application 17 | 18 | The application can be packaged using: 19 | ```shell script 20 | ./mvnw package 21 | ``` 22 | It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory. 23 | Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory. 24 | 25 | The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`. 26 | 27 | If you want to build an _über-jar_, execute the following command: 28 | ```shell script 29 | ./mvnw package -Dquarkus.package.jar.type=uber-jar 30 | ``` 31 | 32 | The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`. 33 | 34 | ## Creating a native executable 35 | 36 | You can create a native executable using: 37 | ```shell script 38 | ./mvnw package -Dnative 39 | ``` 40 | 41 | Or, if you don't have GraalVM installed, you can run the native executable build in a container using: 42 | ```shell script 43 | ./mvnw package -Dnative -Dquarkus.native.container-build=true 44 | ``` 45 | 46 | You can then execute your native executable with: `./target/ai-weather-application-1.0.0-SNAPSHOT-runner` 47 | 48 | If you want to learn more about building native executables, please consult https://quarkus.io/guides/maven-tooling. 49 | 50 | ## Related Guides 51 | 52 | - REST ([guide](https://quarkus.io/guides/rest)): A Jakarta REST implementation utilizing build time processing and Vert.x. This extension is not compatible with the quarkus-resteasy extension, or any of the extensions that depend on it. 53 | - LangChain4j Azure OpenAI ([guide](https://docs.quarkiverse.io/quarkus-langchain4j/dev/index.html)): Provides the basic integration of Azure OpenAi with LangChain4j 54 | 55 | ## Provided Code 56 | 57 | ### REST 58 | 59 | Easily start your REST Web Services 60 | 61 | [Related guide section...](https://quarkus.io/guides/getting-started-reactive#reactive-jax-rs-resources) 62 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/src/main/docker/Dockerfile.legacy-jar: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package -Dquarkus.package.jar.type=legacy-jar 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/ai-weather-application-legacy-jar . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/ai-weather-application-legacy-jar 15 | # 16 | # If you want to include the debug port into your docker image 17 | # you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005. 18 | # Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005 19 | # when running the container 20 | # 21 | # Then run the container using : 22 | # 23 | # docker run -i --rm -p 8080:8080 quarkus/ai-weather-application-legacy-jar 24 | # 25 | # This image uses the `run-java.sh` script to run the application. 26 | # This scripts computes the command line to execute your Java application, and 27 | # includes memory/GC tuning. 28 | # You can configure the behavior using the following environment properties: 29 | # - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") 30 | # - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options 31 | # in JAVA_OPTS (example: "-Dsome.property=foo") 32 | # - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is 33 | # used to calculate a default maximal heap memory based on a containers restriction. 34 | # If used in a container without any memory constraints for the container then this 35 | # option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio 36 | # of the container available memory as set here. The default is `50` which means 50% 37 | # of the available memory is used as an upper boundary. You can skip this mechanism by 38 | # setting this value to `0` in which case no `-Xmx` option is added. 39 | # - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This 40 | # is used to calculate a default initial heap memory based on the maximum heap memory. 41 | # If used in a container without any memory constraints for the container then this 42 | # option has no effect. If there is a memory constraint then `-Xms` is set to a ratio 43 | # of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx` 44 | # is used as the initial heap size. You can skip this mechanism by setting this value 45 | # to `0` in which case no `-Xms` option is added (example: "25") 46 | # - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS. 47 | # This is used to calculate the maximum value of the initial heap memory. If used in 48 | # a container without any memory constraints for the container then this option has 49 | # no effect. If there is a memory constraint then `-Xms` is limited to the value set 50 | # here. The default is 4096MB which means the calculated value of `-Xms` never will 51 | # be greater than 4096MB. The value of this variable is expressed in MB (example: "4096") 52 | # - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output 53 | # when things are happening. This option, if set to true, will set 54 | # `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true"). 55 | # - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example: 56 | # true"). 57 | # - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787"). 58 | # - CONTAINER_CORE_LIMIT: A calculated core limit as described in 59 | # https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2") 60 | # - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024"). 61 | # - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion. 62 | # (example: "20") 63 | # - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking. 64 | # (example: "40") 65 | # - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection. 66 | # (example: "4") 67 | # - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus 68 | # previous GC times. (example: "90") 69 | # - GC_METASPACE_SIZE: The initial metaspace size. (example: "20") 70 | # - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100") 71 | # - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should 72 | # contain the necessary JRE command-line options to specify the required GC, which 73 | # will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC). 74 | # - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080") 75 | # - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080") 76 | # - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be 77 | # accessed directly. (example: "foo.example.com,bar.example.com") 78 | # 79 | ### 80 | FROM registry.access.redhat.com/ubi8/openjdk-21:1.19 81 | 82 | ENV LANGUAGE='en_US:en' 83 | 84 | 85 | COPY target/lib/* /deployments/lib/ 86 | COPY target/*-runner.jar /deployments/quarkus-run.jar 87 | 88 | EXPOSE 8080 89 | USER 185 90 | ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" 91 | ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" 92 | 93 | ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] 94 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/src/main/docker/Dockerfile.native: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package -Dnative 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/ai-weather-application . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/ai-weather-application 15 | # 16 | ### 17 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.9 18 | WORKDIR /work/ 19 | RUN chown 1001 /work \ 20 | && chmod "g+rwX" /work \ 21 | && chown 1001:root /work 22 | COPY --chown=1001:root target/*-runner /work/application 23 | 24 | EXPOSE 8080 25 | USER 1001 26 | 27 | ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] 28 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/src/main/docker/Dockerfile.native-micro: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. 3 | # It uses a micro base image, tuned for Quarkus native executables. 4 | # It reduces the size of the resulting container image. 5 | # Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. 6 | # 7 | # Before building the container image run: 8 | # 9 | # ./mvnw package -Dnative 10 | # 11 | # Then, build the image with: 12 | # 13 | # docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/ai-weather-application . 14 | # 15 | # Then run the container using: 16 | # 17 | # docker run -i --rm -p 8080:8080 quarkus/ai-weather-application 18 | # 19 | ### 20 | FROM quay.io/quarkus/quarkus-micro-image:2.0 21 | WORKDIR /work/ 22 | RUN chown 1001 /work \ 23 | && chmod "g+rwX" /work \ 24 | && chown 1001:root /work 25 | COPY --chown=1001:root target/*-runner /work/application 26 | 27 | EXPOSE 8080 28 | USER 1001 29 | 30 | ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] 31 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/src/main/java/com/example/AiWeatherResource.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import jakarta.inject.Inject; 4 | import jakarta.ws.rs.POST; 5 | import jakarta.ws.rs.Path; 6 | import jakarta.ws.rs.Produces; 7 | import jakarta.ws.rs.core.MediaType; 8 | 9 | import java.io.IOException; 10 | import java.time.LocalDate; 11 | 12 | @Path("/weather") 13 | public class AiWeatherResource { 14 | 15 | private final AiWeatherService aiWeatherService; 16 | private final String weatherHistory; 17 | 18 | @Inject 19 | public AiWeatherResource(AiWeatherService aiWeatherService) throws IOException { 20 | this.aiWeatherService = aiWeatherService; 21 | this.weatherHistory = new String(getClass().getClassLoader().getResourceAsStream("Paris.csv").readAllBytes()); 22 | } 23 | 24 | @Path("/ask") 25 | @POST 26 | @Produces(MediaType.TEXT_PLAIN) 27 | public String askAi(String question) { 28 | 29 | String result = aiWeatherService.ask( 30 | LocalDate.now().toString(), 31 | "Paris", 32 | weatherHistory, 33 | question 34 | ); 35 | 36 | return result; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/src/main/java/com/example/AiWeatherService.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import dev.langchain4j.service.SystemMessage; 4 | import dev.langchain4j.service.UserMessage; 5 | import dev.langchain4j.service.V; 6 | import io.quarkiverse.langchain4j.RegisterAiService; 7 | 8 | @RegisterAiService 9 | public interface AiWeatherService { 10 | 11 | @SystemMessage(""" 12 | Today is {{today}}. 13 | You will act as a meteorological expert who helps analyze and forecast weather. 14 | Given the following historical weather (in CSV format with header) of {{city}} over an entire year, please answer the questions and make predictions. 15 | Don't use any external data. 16 | 17 | {{weatherHistory}} 18 | """ 19 | ) 20 | @UserMessage("{{question}}") 21 | String ask(@V("today") String today, @V("city") String city, @V("weatherHistory") String weatherHistory, @V("question") String question); 22 | } 23 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/src/main/resources/META-INF/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AI Weather Service 6 | 7 | 8 | 9 | 10 | 11 | 12 |

13 | AI Weather Service 14 |

15 |
16 | 17 | 18 | 19 |
20 |

21 | Response: 22 |

23 |
24 | 25 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | quarkus.log.level=INFO 2 | quarkus.http.read-timeout=120s 3 | quarkus.langchain4j.azure-openai.timeout=1m 4 | quarkus.langchain4j.azure-openai.log-requests=true 5 | quarkus.langchain4j.azure-openai.log-responses=true 6 | quarkus.native.resources.includes=Paris.csv 7 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/src/test/java/com/example/AiWeatherResourceIT.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.quarkus.test.junit.QuarkusIntegrationTest; 4 | 5 | @QuarkusIntegrationTest 6 | class AiWeatherResourceIT extends AiWeatherResourceTest { 7 | // Execute the same tests but in packaged mode. 8 | } 9 | -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/ai-weather-application/src/test/java/com/example/AiWeatherResourceTest.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import io.quarkus.test.junit.QuarkusTest; 4 | import org.junit.jupiter.api.Test; 5 | 6 | @QuarkusTest 7 | class AiWeatherResourceTest { 8 | @Test 9 | void testQuarkusContextLoads() { 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/media/01-question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/media/01-question.png -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/media/02-question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/media/02-question.png -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/media/03-question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/media/03-question.png -------------------------------------------------------------------------------- /quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/media/04-question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/quarkus-micronaut/06-build-a-quarkus-ai-application-using-azure-openai/media/04-question.png -------------------------------------------------------------------------------- /quarkus-micronaut/README.md: -------------------------------------------------------------------------------- 1 | # Build, Run and Monitor Intelligent Quarkus and Micronaut Java Apps on Azure Container Apps and Azure OpenAI 2 | 3 | This series of guides focus on building Java applications using Quarkus and Micronaut frameworks and running them on Azure Container Apps. It also covers how to use Azure OpenAI to build AI applications. 4 | 5 | ## [00 - Prerequisites and Setup](00-setup-your-environment/README.md) 6 | 7 | Prerequisites and environment setup. 8 | 9 | ## [01 - Build a simple Java application](01-build-a-simple-java-application/README.md) 10 | 11 | Build the simplest possible Java application using the [Quarkus maven plugin](https://quarkus.io/guides/quarkus-maven-plugin) and [Micronaut Launch](https://launch.micronaut.io/). 12 | 13 | ## [02 - Build a reactive and native Quarkus microservice using PostgreSQL](02-build-a-reactive-and-native-quarkus-microservice-using-postgresql/README.md) 14 | 15 | Build a reactive and native [Quarkus](https://quarkus.io/) microservice that uses [Quarkus Reactive](https://quarkus.io/guides/quarkus-reactive-architecture) and [Quarkus Native](https://quarkus.io/guides/building-native-image). The service is bound to an [Azure Database for PostgreSQL Flexible Server](https://learn.microsoft.com/azure/postgresql/flexible-server/overview), and it uses [Liquibase](https://quarkus.io/guides/liquibase) to manage database schema migrations including initial data population. 16 | 17 | ## [03 - Build a Micronaut microservice using MySQL](03-build-a-micronaut-microservice-using-mysql/README.md) 18 | 19 | Build a [Micronaut](https://micronaut.io/) microserver that uses [Micronaut Data JDBC](https://guides.micronaut.io/latest/micronaut-data-jdbc-repository-maven-java.html). The service is bound to an [Azure Database For MySQL Flexible server](https://learn.microsoft.com/azure/mysql/flexible-server/overview), and it uses [Flyway](https://guides.micronaut.io/latest/micronaut-flyway-maven-java.html) to manage database schema migrations including initial data population. 20 | 21 | ## [04 - Build a NGINX Reverse Proxy](04-build-a-nginx-reverse-proxy/README.md) 22 | 23 | Build a [NGINX Reverse Proxy](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) to route HTTP requests to internal services. 24 | 25 | ## [05 - Putting it all together, a complete microservice stack](05-putting-it-all-together-a-complete-microservice-stack/README.md) 26 | 27 | Use a front-end to access graphically our complete microservice stack. 28 | 29 | ## [06 - Build a Quarkus AI application using Azure OpenAI](06-build-a-quarkus-ai-application-using-azure-openai/README.md) 30 | 31 | Build an AI application that uses [Azure OpenAI Service](https://learn.microsoft.com/en-us/azure/ai-services/openai/) in order to analyze and forecast weather based on historical data. 32 | -------------------------------------------------------------------------------- /spring/00-setup-your-environment/README.md: -------------------------------------------------------------------------------- 1 | # 00 - Setup your environment 2 | 3 | __This guide is part of the [Build, Run and Monitor Intelligent Spring Java Apps on Azure Container Apps and Azure OpenAI](../README.md)__ 4 | 5 | In this section, we'll set up everything you need to expeditiously complete the lab. 6 | 7 | --- 8 | 9 | ## Creating Azure Resources 10 | 11 | To save time, we provide an ARM template for creating all the Azure resources you will need for this lab other than the Azure Container Apps itself. Use the "Deploy to Azure" button below. 12 | 13 | > 💡 Use the following settings for deploying the Azure Template: 14 | > 15 | > * Create a new resource group. 16 | > * In the location field, select the nearest region from [the list of regions where Azure Container Apps is available](https://azure.microsoft.com/global-infrastructure/services/?products=container-apps®ions=all). 17 | > * Save the MySQL password you specify in this step. You will need it in section 6. If you don't set one, it will be `super$ecr3t`. 18 | 19 | [![Deploy to Azure](media/deploybutton.svg)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fmicrosoft%2Fjava-on-aca-with-ai%2Fmain%2Fspring%2F00-setup-your-environment%2Fazuredeploy.json) 20 | 21 | > ⏱ The resource provisioning will take some time. __Do not wait!__ Continue with the workshop. 22 | 23 | > 💡 If the "Deploy to Azure" button above doesn't work, you can try to directly open [https://portal.azure.com/#create/Microsoft.Template/uri/https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/main/spring/00-setup-your-environment/azuredeploy.json](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fmicrosoft%2Fjava-on-aca-with-ai%2Fmain%2Fspring%2F00-setup-your-environment%2Fazuredeploy.json) in your browser, or follow [Create and deploy ARM templates by using the Azure portal](https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/quickstart-create-templates-use-the-portal?source=recommendations) to deploy the [azuredeploy.json](azuredeploy.json) file. 24 | 25 | ## Prerequisites 26 | 27 | This training lab requires the following to be installed on your machine: 28 | 29 | * [JDK 17](https://docs.microsoft.com/java/openjdk/download#openjdk-17) 30 | * A text editor or an IDE. If you do not already have an IDE for Java development, we recommend using [Visual Studio Code](https://code.visualstudio.com) with the [Java Extension Pack](https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack). 31 | 32 | * The Bash shell. While Azure CLI should behave identically on all environments, shell semantics vary. Therefore, only bash can be used with the commands in this training. To complete this training on Windows, use [Windows Subsystem for Linux](https://learn.microsoft.com/windows/wsl/install). 33 | 34 | * [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) version 2.61.0 or later. You can check the version of your current Azure CLI installation by running: 35 | 36 | ```bash 37 | az --version 38 | ``` 39 | 40 | > 💡 If you try the command above and you see the error `bash: az: command not found`, run the following command: `alias az='az.cmd'` and try again. 41 | 42 | * 🚧 The `containerapp` extension for Azure CLI. You can install or update this extension after installing Azure CLI by running `az extension add --name containerapp --upgrade --allow-preview true`. 43 | 44 | > 💡 In some sections, you will access the UI of the Microservice applications in a web browser. Use the [Microsoft Edge](https://microsoft.com/edge), Google Chrome, or Firefox for these sections. 45 | 46 | The environment variable `JAVA_HOME` should be set to the path of the JDK installation. The directory specified by this path should have `bin`, `jre`, and `lib` among its subdirectories. Further, ensure your `PATH` variable contains the directory `${JAVA_HOME}/bin`. To test, type `which javac` into bash shell ensure the resulting path points to a file inside `${JAVA_HOME}/bin`. 47 | 48 | You can then use Visual Studio Code or an IDE of your choice. 49 | 50 | --- 51 | 52 | ➡️ Next guide: [01 - Build a simple Java application](../01-build-a-simple-java-application/README.md) 53 | -------------------------------------------------------------------------------- /spring/00-setup-your-environment/azuredeploy.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "location": { 6 | "value": "canadacentral" 7 | }, 8 | "mysql_admin_password": { 9 | "value": "super$ecr3t" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /spring/01-build-a-simple-java-application/media/01-application-url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/01-build-a-simple-java-application/media/01-application-url.png -------------------------------------------------------------------------------- /spring/01-build-a-simple-java-application/simple-application/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /spring/01-build-a-simple-java-application/simple-application/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/01-build-a-simple-java-application/simple-application/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /spring/01-build-a-simple-java-application/simple-application/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /spring/01-build-a-simple-java-application/simple-application/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.2.5 9 | 10 | 11 | com.example 12 | demo 13 | 0.0.1-SNAPSHOT 14 | simple-application 15 | Demo project for Spring Boot 16 | 17 | 17 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-test 28 | test 29 | 30 | 31 | 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-maven-plugin 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /spring/01-build-a-simple-java-application/simple-application/src/main/java/com/example/demo/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class HelloController { 8 | 9 | @GetMapping("/hello") 10 | public String hello() { 11 | return "Hello from Java application on Azure Container Apps\n"; 12 | } 13 | } -------------------------------------------------------------------------------- /spring/01-build-a-simple-java-application/simple-application/src/main/java/com/example/demo/SimpleApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SimpleApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SimpleApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/01-build-a-simple-java-application/simple-application/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=simple-application 2 | -------------------------------------------------------------------------------- /spring/01-build-a-simple-java-application/simple-application/src/test/java/com/example/demo/SimpleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SimpleApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/02-create-managed-eureka-server-for-spring/README.md: -------------------------------------------------------------------------------- 1 | # 02 - Create Managed Eureka Server for Spring 2 | 3 | __This guide is part of the [Build, Run and Monitor Intelligent Spring Java Apps on Azure Container Apps and Azure OpenAI](../README.md)__ 4 | 5 | A key feature of cloud-native application is *service discovery* - the ability to provide a common place to find and identify individual services. In this section, we'll create a [Spring Cloud Eureka Server](https://spring.io/projects/spring-cloud-netflix) to enable this functionality. 6 | 7 | --- 8 | 9 | ## Create a Managed Eureka Server 10 | 11 | Define the environment variables. Please note that those environment variables defined in [01 - Build a simple Java application](../01-build-a-simple-java-application/README.md) will also be used. 12 | 13 | ```bash 14 | EUREKA_SERVER_NAME="eurekaserver01" 15 | ``` 16 | 17 | Create the Managed Eureka Server. 18 | 19 | ```bash 20 | az containerapp env java-component eureka-server-for-spring create \ 21 | --environment $ENVIRONMENT \ 22 | --resource-group $RESOURCE_GROUP \ 23 | --name $EUREKA_SERVER_NAME 24 | ``` 25 | 26 | ## Review 27 | 28 | We have enabled Azure Container Apps to create a Managed Eureka Server for Spring. 29 | 30 | In the next section, we will create a Managed Config Server for Spring, to enable to ability of *externalized configuration*. 31 | 32 | --- 33 | 34 | ⬅️ Previous guide: [01 - Build a simple Java application](../01-build-a-simple-java-application/README.md) 35 | 36 | ➡️ Next guide: [03 - Create and configure Managed Config Server for Spring](../03-create-and-configure-managed-config-server-for-spring/README.md) 37 | -------------------------------------------------------------------------------- /spring/03-create-and-configure-managed-config-server-for-spring/media/01-github-personal-access-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/03-create-and-configure-managed-config-server-for-spring/media/01-github-personal-access-token.png -------------------------------------------------------------------------------- /spring/03-create-and-configure-managed-config-server-for-spring/media/02-github-token-select-repositories.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/03-create-and-configure-managed-config-server-for-spring/media/02-github-token-select-repositories.png -------------------------------------------------------------------------------- /spring/03-create-and-configure-managed-config-server-for-spring/media/03-github-repo-permission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/03-create-and-configure-managed-config-server-for-spring/media/03-github-repo-permission.png -------------------------------------------------------------------------------- /spring/03-create-and-configure-managed-config-server-for-spring/media/04-github-repo-permission-content-readonly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/03-create-and-configure-managed-config-server-for-spring/media/04-github-repo-permission-content-readonly.png -------------------------------------------------------------------------------- /spring/03-create-and-configure-managed-config-server-for-spring/media/05-github-generate-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/03-create-and-configure-managed-config-server-for-spring/media/05-github-generate-token.png -------------------------------------------------------------------------------- /spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/media/01-exception-stack-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/media/01-exception-stack-trace.png -------------------------------------------------------------------------------- /spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/media/02-console-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/media/02-console-output.png -------------------------------------------------------------------------------- /spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/media/03-logs-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/media/03-logs-query.png -------------------------------------------------------------------------------- /spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/spring-cloud-microservice/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/spring-cloud-microservice/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/spring-cloud-microservice/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/spring-cloud-microservice/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/spring-cloud-microservice/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.2.5 9 | 10 | 11 | com.example 12 | demo 13 | 0.0.1-SNAPSHOT 14 | spring-cloud-microservice 15 | Demo project for Spring Boot 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 17 31 | 2023.0.2 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-web 37 | 38 | 39 | org.springframework.cloud 40 | spring-cloud-starter-config 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-netflix-eureka-client 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | 54 | 55 | 56 | org.springframework.cloud 57 | spring-cloud-dependencies 58 | ${spring-cloud.version} 59 | pom 60 | import 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | org.springframework.boot 69 | spring-boot-maven-plugin 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/spring-cloud-microservice/src/main/java/com/example/demo/HelloController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | public class HelloController { 9 | 10 | @Value("${application.message:Not configured by Spring Cloud Config Server}") 11 | private String message; 12 | 13 | @GetMapping("/hello") 14 | public String hello() { 15 | return message + '\n'; 16 | } 17 | } -------------------------------------------------------------------------------- /spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/spring-cloud-microservice/src/main/java/com/example/demo/SpringCloudMicroserviceApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringCloudMicroserviceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringCloudMicroserviceApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/spring-cloud-microservice/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=spring-cloud-microservice 2 | spring.config.import=optional:configserver: -------------------------------------------------------------------------------- /spring/04-build-a-spring-boot-microservice-using-spring-cloud-features/spring-cloud-microservice/src/test/java/com/example/demo/SpringCloudMicroserviceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringCloudMicroserviceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/city-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/city-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/city-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/city-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/city-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.2.5 9 | 10 | 11 | com.example 12 | demo 13 | 0.0.1-SNAPSHOT 14 | city-service 15 | Demo project for Spring Boot 16 | 17 | 17 18 | 2023.0.1 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-webflux 24 | 25 | 26 | org.springframework.cloud 27 | spring-cloud-starter-config 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-starter-netflix-eureka-client 32 | 33 | 34 | com.azure 35 | azure-cosmos 36 | 4.59.0 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-test 42 | test 43 | 44 | 45 | io.projectreactor 46 | reactor-test 47 | test 48 | 49 | 50 | 51 | 52 | 53 | org.springframework.cloud 54 | spring-cloud-dependencies 55 | ${spring-cloud.version} 56 | pom 57 | import 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-maven-plugin 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/city-service/src/main/java/com/example/demo/City.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | class City { 4 | 5 | private String name; 6 | 7 | public String getName() { 8 | return name; 9 | } 10 | 11 | public void setName(String name) { 12 | this.name = name; 13 | } 14 | } -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/city-service/src/main/java/com/example/demo/CityController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import com.azure.cosmos.CosmosAsyncContainer; 4 | import com.azure.cosmos.CosmosClientBuilder; 5 | import com.azure.cosmos.models.CosmosQueryRequestOptions; 6 | import com.azure.cosmos.models.FeedResponse; 7 | 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import reactor.core.publisher.Flux; 12 | 13 | import jakarta.annotation.PostConstruct; 14 | import java.util.List; 15 | 16 | @RestController 17 | public class CityController { 18 | 19 | @Value("${azure.cosmos.uri}") 20 | private String cosmosDbUrl; 21 | 22 | @Value("${azure.cosmos.key}") 23 | private String cosmosDbKey; 24 | 25 | @Value("${azure.cosmos.database}") 26 | private String cosmosDbDatabase; 27 | 28 | private CosmosAsyncContainer container; 29 | 30 | @PostConstruct 31 | public void init() { 32 | container = new CosmosClientBuilder() 33 | .endpoint(cosmosDbUrl) 34 | .key(cosmosDbKey) 35 | .buildAsyncClient() 36 | .getDatabase(cosmosDbDatabase) 37 | .getContainer("City"); 38 | } 39 | 40 | @GetMapping("/cities") 41 | public Flux> getCities() { 42 | CosmosQueryRequestOptions options = new CosmosQueryRequestOptions(); 43 | return container.queryItems("SELECT TOP 20 * FROM City c", options, City.class) 44 | .byPage() 45 | .map(FeedResponse::getResults); 46 | } 47 | } -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/city-service/src/main/java/com/example/demo/CityServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CityServiceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CityServiceApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/city-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=city-service 2 | -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/city-service/src/test/java/com/example/demo/CityServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CityServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/media/01-data-explorer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/media/01-data-explorer.png -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/media/02-service-connector-cosmos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/media/02-service-connector-cosmos.png -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/media/03-service-connector-cosmos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/media/03-service-connector-cosmos.png -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/media/04-service-connector-cosmos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/media/04-service-connector-cosmos.png -------------------------------------------------------------------------------- /spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/media/05-service-connector-cosmos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/05-build-a-reactive-spring-boot-microservice-using-cosmosdb/media/05-service-connector-cosmos.png -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/media/01-create-service-connector-mysql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/06-build-a-spring-boot-microservice-using-mysql/media/01-create-service-connector-mysql.png -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/media/02-create-service-connector-mysql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/06-build-a-spring-boot-microservice-using-mysql/media/02-create-service-connector-mysql.png -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/media/03-create-service-connector-mysql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/06-build-a-spring-boot-microservice-using-mysql/media/03-create-service-connector-mysql.png -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/media/04-create-service-connector-mysql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/06-build-a-spring-boot-microservice-using-mysql/media/04-create-service-connector-mysql.png -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.2.5 9 | 10 | 11 | com.example 12 | demo 13 | 0.0.1-SNAPSHOT 14 | weather-service 15 | Demo project for Spring Boot 16 | 17 | 17 18 | 2023.0.1 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-data-jpa 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-web 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-starter-config 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-starter-netflix-eureka-client 36 | 37 | 38 | 39 | com.mysql 40 | mysql-connector-j 41 | runtime 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-test 46 | test 47 | 48 | 49 | 50 | 51 | 52 | org.springframework.cloud 53 | spring-cloud-dependencies 54 | ${spring-cloud.version} 55 | pom 56 | import 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | org.springframework.boot 65 | spring-boot-maven-plugin 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/src/main/java/com/example/demo/Weather.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.Id; 5 | 6 | @Entity 7 | public class Weather { 8 | 9 | @Id 10 | private String city; 11 | 12 | private String description; 13 | 14 | private String icon; 15 | 16 | public String getCity() { 17 | return city; 18 | } 19 | 20 | public void setCity(String city) { 21 | this.city = city; 22 | } 23 | 24 | public String getDescription() { 25 | return description; 26 | } 27 | 28 | public void setDescription(String description) { 29 | this.description = description; 30 | } 31 | 32 | public String getIcon() { 33 | return icon; 34 | } 35 | 36 | public void setIcon(String icon) { 37 | this.icon = icon; 38 | } 39 | } -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/src/main/java/com/example/demo/WeatherController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.web.bind.annotation.*; 4 | 5 | import java.util.Optional; 6 | 7 | @RestController 8 | @RequestMapping("/weather") 9 | public class WeatherController { 10 | 11 | private final WeatherRepository weatherRepository; 12 | 13 | public WeatherController(WeatherRepository weatherRepository) { 14 | this.weatherRepository = weatherRepository; 15 | } 16 | 17 | @GetMapping("/city") 18 | public Optional getWeatherForCity(@RequestParam("name") String cityName) { 19 | return weatherRepository.findById(cityName); 20 | } 21 | } -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/src/main/java/com/example/demo/WeatherRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | public interface WeatherRepository extends CrudRepository { 6 | } -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/src/main/java/com/example/demo/WeatherServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class WeatherServiceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(WeatherServiceApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=weather-service 2 | spring.jpa.hibernate.ddl-auto=create 3 | spring.sql.init.continue-on-error=true -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/src/main/resources/import.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO `java-on-aca-db`.`weather` (`city`, `description`, `icon`) VALUES ('Paris, France', 'Very cloudy!', 'weather-fog'); 2 | INSERT INTO `java-on-aca-db`.`weather` (`city`, `description`, `icon`) VALUES ('London, UK', 'Quite cloudy', 'weather-pouring'); 3 | -------------------------------------------------------------------------------- /spring/06-build-a-spring-boot-microservice-using-mysql/weather-service/src/test/java/com/example/demo/WeatherServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class WeatherServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/07-build-a-spring-cloud-gateway/README.md: -------------------------------------------------------------------------------- 1 | # 07 - Build a Spring Cloud Gateway 2 | 3 | __This guide is part of the [Build, Run and Monitor Intelligent Spring Java Apps on Azure Container Apps and Azure OpenAI](../README.md)__ 4 | 5 | A Spring Cloud gateway allows you to selectively expose your microservices and to route traffic to them and among them. In this section, we will create a Spring Cloud Gateway that will expose the microservices we created in the preceding two sections. 6 | 7 | --- 8 | 9 | ## Create a Spring Cloud Gateway 10 | 11 | The application that we create in this guide is [available here](gateway/). 12 | 13 | To create our gateway, we will invoke the Spring Initalizr service from the command line: 14 | 15 | ```bash 16 | curl https://start.spring.io/starter.tgz \ 17 | -d type=maven-project \ 18 | -d dependencies=cloud-gateway-reactive,cloud-eureka,cloud-config-client \ 19 | -d baseDir=gateway \ 20 | -d name=gateway \ 21 | -d bootVersion=3.2.5 \ 22 | -d javaVersion=17 \ 23 | | tar -xzvf - 24 | ``` 25 | 26 | > We use the `Cloud Gateway Reactive`, `Eureka Discovery Client` and the `Config Client` components. 27 | 28 | ## Configure the application 29 | 30 | Open `src/main/resources/application.properties` and add the following configuration: 31 | 32 | ```properties 33 | spring.application.name=gateway 34 | spring.cloud.gateway.discovery.locator.enabled=true 35 | spring.cloud.gateway.discovery.locator.lowerCaseServiceId=true 36 | spring.cloud.gateway.globalcors.corsConfigurations.[/**].allowedOrigins=* 37 | spring.cloud.gateway.globalcors.corsConfigurations.[/**].allowedMethods=GET 38 | ``` 39 | 40 | - The `spring.cloud.gateway.discovery.locator.enabled=true` part is to configure Spring Cloud Gateway to use the Spring Cloud Service Registry to discover the available microservices. 41 | - The `spring.cloud.gateway.globalcors.corsConfiguration` part is to allow Cross-Origin Resource Sharing (CORS) requests to our gateway. This will be helpful in the next guide, when we will add a front-end application. 42 | 43 | ## Create the application on Azure Container Apps 44 | 45 | As in [01 - Build a simple Java application](../01-build-a-simple-java-application/README.md), create a specific `gateway` application. 46 | 47 | ```bash 48 | cd gateway 49 | ./mvnw clean package -DskipTests 50 | az containerapp create \ 51 | --name gateway \ 52 | --resource-group $RESOURCE_GROUP \ 53 | --environment $ENVIRONMENT \ 54 | --artifact ./target/demo-0.0.1-SNAPSHOT.jar \ 55 | --min-replicas 1 \ 56 | --ingress external \ 57 | --bind $CONFIG_SERVER_NAME $EUREKA_SERVER_NAME \ 58 | --target-port 8080 59 | cd .. 60 | ``` 61 | 62 | ## Test the project in the cloud 63 | 64 | - Go to your container app `gateway` 65 | - Find the "Application Url" in the "Essentials" section 66 | 67 | As the gateway is connected to the Spring Cloud Eureka Server, it should have automatically opened routes to the available microservices, with URL paths in the form of `/microservice-id/**`. For example: 68 | 69 | - Test the `city-service` microservice endpoint: 70 | ``` 71 | curl https://gateway.victorioussky-9afe1793.canadacentral.azurecontainerapps.io/city-service/cities 72 | ``` 73 | - Test the `weather-service` microservice endpoint by doing: 74 | ``` 75 | curl https://gateway.victorioussky-9afe1793.canadacentral.azurecontainerapps.io/weather-service/weather/city?name=Paris%2C%20France 76 | ``` 77 | 78 | If you need to check your code, the final project is available in the ["gateway" folder](gateway/). 79 | 80 | --- 81 | 82 | ⬅️ Previous guide: [06 - Build a Spring Boot microservice using MySQL](../06-build-a-spring-boot-microservice-using-mysql/README.md) 83 | 84 | ➡️ Next guide: [08 - Putting it all together, a complete microservice stack](../08-putting-it-all-together-a-complete-microservice-stack/README.md) -------------------------------------------------------------------------------- /spring/07-build-a-spring-cloud-gateway/gateway/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /spring/07-build-a-spring-cloud-gateway/gateway/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/07-build-a-spring-cloud-gateway/gateway/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /spring/07-build-a-spring-cloud-gateway/gateway/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /spring/07-build-a-spring-cloud-gateway/gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.2.5 9 | 10 | 11 | com.example 12 | demo 13 | 0.0.1-SNAPSHOT 14 | gateway 15 | Demo project for Spring Boot 16 | 17 | 17 18 | 2023.0.1 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-config 24 | 25 | 26 | org.springframework.cloud 27 | spring-cloud-starter-gateway 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-starter-netflix-eureka-client 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | io.projectreactor 41 | reactor-test 42 | test 43 | 44 | 45 | 46 | 47 | 48 | org.springframework.cloud 49 | spring-cloud-dependencies 50 | ${spring-cloud.version} 51 | pom 52 | import 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | org.springframework.boot 61 | spring-boot-maven-plugin 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /spring/07-build-a-spring-cloud-gateway/gateway/src/main/java/com/example/demo/GatewayApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class GatewayApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(GatewayApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/07-build-a-spring-cloud-gateway/gateway/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=gateway 2 | spring.cloud.gateway.discovery.locator.enabled=true 3 | spring.cloud.gateway.discovery.locator.lowerCaseServiceId=true 4 | spring.cloud.gateway.globalcors.corsConfigurations.[/**].allowedOrigins=* 5 | spring.cloud.gateway.globalcors.corsConfigurations.[/**].allowedMethods=GET -------------------------------------------------------------------------------- /spring/07-build-a-spring-cloud-gateway/gateway/src/test/java/com/example/demo/GatewayApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class GatewayApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/README.md: -------------------------------------------------------------------------------- 1 | # 08 - Putting it all together, a complete microservice stack 2 | 3 | __This guide is part of the [Build, Run and Monitor Intelligent Spring Java Apps on Azure Container Apps and Azure OpenAI](../README.md)__ 4 | 5 | Now that we have made microservices publicly available, we will incorporate a user interface to see them in action. Then, we will use Azure Monitor to monitor the flow of traffic to and among our services and to track metrics. 6 | 7 | --- 8 | 9 | ## Add a front-end to the microservices stack 10 | 11 | We now have a complete microservices stack: 12 | 13 | - A `gateway` based on Spring Cloud Gateway. 14 | - A reactive `city-service` microservice, that stores its data in Azure Cosmos DB. 15 | - A `weather-service` microservice, that stores its data in MySQL. 16 | 17 | In order to finish this architecture, we need to add a front-end to it: 18 | 19 | - We've already built a VueJS application, that is available in the ["weather-app" folder](weather-app/). 20 | - This front-end will be hosted on Azure Container Apps as well, with its own domain name. That's why we enabled CORS in our gateway earlier. 21 | - If you are familiar with NodeJS and Vue CLI, you can also run this application locally by typing `npm install && vue ui`. 22 | 23 | In order to simplify this part, which is not relevant to understanding Java and Spring, we have already containerized the front-end application and put it in `mcr.microsoft.com/javaaccelerator/samples/weather-app:latest`. You can use it directly. 24 | 25 | ```bash 26 | az containerapp create \ 27 | --name weather-app \ 28 | --resource-group $RESOURCE_GROUP \ 29 | --environment $ENVIRONMENT \ 30 | --image mcr.microsoft.com/javaaccelerator/samples/weather-app:latest \ 31 | --ingress external \ 32 | --target-port 80 33 | ``` 34 | 35 | After created, find its "Application Url" and open it in your browser. The "Spring Cloud Gateway URL" is automatically populated with your gateway address. Click on "Go" and you should see the following screen: 36 | 37 | ![VueJS front-end](media/01-vuejs-frontend.png) 38 | 39 | ⬅️ Previous guide: [07 - Build a Spring Cloud Gateway](../07-build-a-spring-cloud-gateway/README.md) 40 | 41 | ➡️ Next guide: [09 - Build a Spring AI application using Azure OpenAI](../09-build-a-spring-ai-application-using-azure-openai/README.md) 42 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/media/01-vuejs-frontend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/08-putting-it-all-together-a-complete-microservice-stack/media/01-vuejs-frontend.png -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | not ie 11 5 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/Dockerfile: -------------------------------------------------------------------------------- 1 | # build stage 2 | FROM node:23 AS build-stage 3 | WORKDIR /app 4 | COPY package*.json ./ 5 | RUN npm install 6 | COPY . . 7 | RUN npm run build 8 | 9 | # production stage 10 | FROM nginx:stable-alpine AS production-stage 11 | COPY --from=build-stage /app/dist /usr/share/nginx/html 12 | COPY ./docker/entrypoint.sh /entrypoint.sh 13 | RUN chmod +x /entrypoint.sh 14 | EXPOSE 80 15 | ENV GATEWAY_NAME=gateway 16 | ENTRYPOINT ["/entrypoint.sh"] 17 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/README.md: -------------------------------------------------------------------------------- 1 | # Vuetify (Default) 2 | 3 | This is the official scaffolding tool for Vuetify, designed to give you a head start in building your new Vuetify application. It sets up a base template with all the necessary configurations and standard directory structure, enabling you to begin development without the hassle of setting up the project from scratch. 4 | 5 | ## ❗️ Important Links 6 | 7 | - 📄 [Docs](https://vuetifyjs.com/) 8 | - 🚨 [Issues](https://issues.vuetifyjs.com/) 9 | - 🏬 [Store](https://store.vuetifyjs.com/) 10 | - 🎮 [Playground](https://play.vuetifyjs.com/) 11 | - 💬 [Discord](https://community.vuetifyjs.com) 12 | 13 | ## 💿 Install 14 | 15 | Set up your project using your preferred package manager. Use the corresponding command to install the dependencies: 16 | 17 | | Package Manager | Command | 18 | |---------------------------------------------------------------|----------------| 19 | | [yarn](https://yarnpkg.com/getting-started) | `yarn install` | 20 | | [npm](https://docs.npmjs.com/cli/v7/commands/npm-install) | `npm install` | 21 | | [pnpm](https://pnpm.io/installation) | `pnpm install` | 22 | | [bun](https://bun.sh/#getting-started) | `bun install` | 23 | 24 | After completing the installation, your environment is ready for Vuetify development. 25 | 26 | ## ✨ Features 27 | 28 | - 🖼️ **Optimized Front-End Stack**: Leverage the latest Vue 3 and Vuetify 3 for a modern, reactive UI development experience. [Vue 3](https://v3.vuejs.org/) | [Vuetify 3](https://vuetifyjs.com/en/) 29 | - 🗃️ **State Management**: Integrated with [Pinia](https://pinia.vuejs.org/), the intuitive, modular state management solution for Vue. 30 | - 🚦 **Routing and Layouts**: Utilizes Vue Router for SPA navigation and vite-plugin-vue-layouts for organizing Vue file layouts. [Vue Router](https://router.vuejs.org/) | [vite-plugin-vue-layouts](https://github.com/JohnCampionJr/vite-plugin-vue-layouts) 31 | - ⚡ **Next-Gen Tooling**: Powered by Vite, experience fast cold starts and instant HMR (Hot Module Replacement). [Vite](https://vitejs.dev/) 32 | - 🧩 **Automated Component Importing**: Streamline your workflow with unplugin-vue-components, automatically importing components as you use them. [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components) 33 | 34 | These features are curated to provide a seamless development experience from setup to deployment, ensuring that your Vuetify application is both powerful and maintainable. 35 | 36 | ## 💡 Usage 37 | 38 | This section covers how to start the development server and build your project for production. 39 | 40 | ### Starting the Development Server 41 | 42 | To start the development server with hot-reload, run the following command. The server will be accessible at [http://localhost:3000](http://localhost:3000): 43 | 44 | ```bash 45 | yarn dev 46 | ``` 47 | 48 | (Repeat for npm, pnpm, and bun with respective commands.) 49 | 50 | > Add NODE_OPTIONS='--no-warnings' to suppress the JSON import warnings that happen as part of the Vuetify import mapping. If you are on Node [v21.3.0](https://nodejs.org/en/blog/release/v21.3.0) or higher, you can change this to NODE_OPTIONS='--disable-warning=5401'. If you don't mind the warning, you can remove this from your package.json dev script. 51 | 52 | ### Building for Production 53 | 54 | To build your project for production, use: 55 | 56 | ```bash 57 | yarn build 58 | ``` 59 | 60 | (Repeat for npm, pnpm, and bun with respective commands.) 61 | 62 | Once the build process is completed, your application will be ready for deployment in a production environment. 63 | 64 | ## 💪 Support Vuetify Development 65 | 66 | This project is built with [Vuetify](https://vuetifyjs.com/en/), a UI Library with a comprehensive collection of Vue components. Vuetify is an MIT licensed Open Source project that has been made possible due to the generous contributions by our [sponsors and backers](https://vuetifyjs.com/introduction/sponsors-and-backers/). If you are interested in supporting this project, please consider: 67 | 68 | - [Requesting Enterprise Support](https://support.vuetifyjs.com/) 69 | - [Sponsoring John on Github](https://github.com/users/johnleider/sponsorship) 70 | - [Sponsoring Kael on Github](https://github.com/users/kaelwd/sponsorship) 71 | - [Supporting the team on Open Collective](https://opencollective.com/vuetify) 72 | - [Becoming a sponsor on Patreon](https://www.patreon.com/vuetify) 73 | - [Becoming a subscriber on Tidelift](https://tidelift.com/subscription/npm/vuetify) 74 | - [Making a one-time donation with Paypal](https://paypal.me/vuetify) 75 | 76 | ## 📑 License 77 | [MIT](http://opensource.org/licenses/MIT) 78 | 79 | Copyright (c) 2016-present Vuetify, LLC 80 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/docker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ROOT_DIR=/usr/share/nginx/html 4 | 5 | # Replace env vars in JavaScript files 6 | echo "Replacing env constants in JS" 7 | for file in $ROOT_DIR/assets/*.js; 8 | do 9 | echo "Processing $file ..."; 10 | sed -i 's|CONTAINER_APP_ENV_DNS_SUFFIX|'${CONTAINER_APP_ENV_DNS_SUFFIX}'|g' $file 11 | sed -i 's|GATEWAY_NAME|'${GATEWAY_NAME}'|g' $file 12 | done 13 | 14 | echo "Starting Nginx" 15 | nginx -g 'daemon off;' -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import globals from "globals"; 2 | import pluginJs from "@eslint/js"; 3 | import pluginVue from "eslint-plugin-vue"; 4 | 5 | 6 | export default [ 7 | {files: ["**/*.{js,mjs,cjs,vue}"]}, 8 | {languageOptions: { globals: globals.browser }}, 9 | pluginJs.configs.recommended, 10 | ...pluginVue.configs["flat/essential"], 11 | ]; -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | What's the weather today? 12 | 13 | 14 | 15 | 18 |
19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "target": "es5", 5 | "module": "esnext", 6 | "baseUrl": "./", 7 | "moduleResolution": "bundler", 8 | "paths": { 9 | "@/*": [ 10 | "src/*" 11 | ] 12 | }, 13 | "lib": [ 14 | "esnext", 15 | "dom", 16 | "dom.iterable", 17 | "scripthost" 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weather-app", 3 | "version": "0.1.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vite build", 7 | "preview": "vite preview" 8 | }, 9 | "dependencies": { 10 | "@mdi/font": "7.4.47", 11 | "roboto-fontface": "*", 12 | "vue": "^3.4.31", 13 | "vuetify": "^3.6.11" 14 | }, 15 | "devDependencies": { 16 | "@eslint/js": "^9.13.0", 17 | "@vitejs/plugin-vue": "^5.0.5", 18 | "eslint": "^9.13.0", 19 | "eslint-plugin-vue": "^9.29.1", 20 | "globals": "^15.11.0", 21 | "sass": "1.77.6", 22 | "unplugin-fonts": "^1.1.1", 23 | "unplugin-vue-components": "^0.27.2", 24 | "vite": "^5.3.3", 25 | "vite-plugin-vuetify": "^2.0.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/public/favicon.ico -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/src/App.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 49 | 50 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/src/components/WeatherComponent.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 86 | 87 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/src/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * main.js 3 | * 4 | * Bootstraps Vuetify and other plugins then mounts the App` 5 | */ 6 | 7 | // Plugins 8 | import { registerPlugins } from '@/plugins' 9 | 10 | // Components 11 | import App from './App.vue' 12 | 13 | // Composables 14 | import { createApp } from 'vue' 15 | 16 | const app = createApp(App) 17 | 18 | registerPlugins(app) 19 | 20 | app.mount('#app') 21 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/src/plugins/README.md: -------------------------------------------------------------------------------- 1 | # Plugins 2 | 3 | Plugins are a way to extend the functionality of your Vue application. Use this folder for registering plugins that you want to use globally. 4 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/src/plugins/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * plugins/index.js 3 | * 4 | * Automatically included in `./src/main.js` 5 | */ 6 | 7 | // Plugins 8 | import vuetify from './vuetify' 9 | 10 | export function registerPlugins (app) { 11 | app.use(vuetify) 12 | } 13 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/src/plugins/vuetify.js: -------------------------------------------------------------------------------- 1 | /** 2 | * plugins/vuetify.js 3 | * 4 | * Framework documentation: https://vuetifyjs.com` 5 | */ 6 | 7 | // Styles 8 | import '@mdi/font/css/materialdesignicons.css' 9 | import 'vuetify/styles' 10 | 11 | // Composables 12 | import { createVuetify } from 'vuetify' 13 | 14 | // https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides 15 | export default createVuetify({ 16 | theme: { 17 | defaultTheme: 'light', 18 | }, 19 | }) 20 | -------------------------------------------------------------------------------- /spring/08-putting-it-all-together-a-complete-microservice-stack/weather-app/vite.config.mjs: -------------------------------------------------------------------------------- 1 | // Plugins 2 | import Components from 'unplugin-vue-components/vite' 3 | import Vue from '@vitejs/plugin-vue' 4 | import Vuetify, { transformAssetUrls } from 'vite-plugin-vuetify' 5 | import ViteFonts from 'unplugin-fonts/vite' 6 | 7 | // Utilities 8 | import { defineConfig } from 'vite' 9 | import { fileURLToPath, URL } from 'node:url' 10 | 11 | // https://vitejs.dev/config/ 12 | export default defineConfig({ 13 | plugins: [ 14 | Vue({ 15 | template: { transformAssetUrls } 16 | }), 17 | // https://github.com/vuetifyjs/vuetify-loader/tree/master/packages/vite-plugin#readme 18 | Vuetify(), 19 | Components(), 20 | ViteFonts({ 21 | google: { 22 | families: [{ 23 | name: 'Roboto', 24 | styles: 'wght@100;300;400;500;700;900', 25 | }], 26 | }, 27 | }), 28 | ], 29 | define: { 'process.env': {} }, 30 | resolve: { 31 | alias: { 32 | '@': fileURLToPath(new URL('./src', import.meta.url)) 33 | }, 34 | extensions: [ 35 | '.js', 36 | '.json', 37 | '.jsx', 38 | '.mjs', 39 | '.ts', 40 | '.tsx', 41 | '.vue', 42 | ], 43 | }, 44 | server: { 45 | port: 3000, 46 | }, 47 | }) 48 | -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/ai-weather-application/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/ai-weather-application/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/09-build-a-spring-ai-application-using-azure-openai/ai-weather-application/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/ai-weather-application/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/ai-weather-application/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.2.5 9 | 10 | 11 | com.example 12 | demo 13 | 0.0.1-SNAPSHOT 14 | ai-weather-application 15 | Demo project for Spring Boot 16 | 17 | 17 18 | 0.8.1 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-web 24 | 25 | 26 | org.springframework.ai 27 | spring-ai-azure-openai-spring-boot-starter 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-test 33 | test 34 | 35 | 36 | 37 | 38 | 39 | org.springframework.ai 40 | spring-ai-bom 41 | ${spring-ai.version} 42 | pom 43 | import 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-maven-plugin 53 | 54 | 55 | 56 | 57 | 58 | spring-milestones 59 | Spring Milestones 60 | https://repo.spring.io/milestone 61 | 62 | false 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/ai-weather-application/src/main/java/com/example/demo/AiWeatherApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class AiWeatherApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(AiWeatherApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/ai-weather-application/src/main/java/com/example/demo/AiWeatherController.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.ai.azure.openai.AzureOpenAiChatClient; 4 | import org.springframework.ai.chat.ChatResponse; 5 | import org.springframework.ai.chat.messages.Message; 6 | import org.springframework.ai.chat.messages.UserMessage; 7 | import org.springframework.ai.chat.prompt.Prompt; 8 | import org.springframework.ai.chat.prompt.PromptTemplate; 9 | import org.springframework.ai.chat.prompt.SystemPromptTemplate; 10 | import org.springframework.beans.factory.annotation.Value; 11 | import org.springframework.core.io.Resource; 12 | import org.springframework.web.bind.annotation.PostMapping; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RequestParam; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | import java.time.LocalDate; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | @RestController 22 | @RequestMapping(path = "/weather") 23 | public class AiWeatherController { 24 | 25 | private final AzureOpenAiChatClient chatClient; 26 | 27 | @Value("classpath:/static/prompt.template") 28 | private Resource promptTemplate; 29 | 30 | @Value("classpath:/static/Paris.csv") 31 | private Resource parisWeatherData; 32 | 33 | public AiWeatherController(AzureOpenAiChatClient chatClient) { 34 | this.chatClient = chatClient; 35 | } 36 | 37 | @PostMapping("/ask") 38 | public ChatResponse askAi(@RequestParam String question) { 39 | PromptTemplate systemMessageTemplate = new SystemPromptTemplate(promptTemplate); 40 | Message systemMessage = systemMessageTemplate.createMessage( 41 | Map.of("today", LocalDate.now().toString(), 42 | "city", "Paris", 43 | "weatherHistory", parisWeatherData)); 44 | Prompt prompt = new Prompt(List.of(systemMessage, new UserMessage(question))); 45 | return chatClient.call(prompt); 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/ai-weather-application/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=ai-weather-application 2 | spring.ai.azure.openai.chat.options.deployment-name=gpt-35-turbo-16k 3 | spring.ai.azure.openai.chat.options.temperature=0 -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/ai-weather-application/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AI Weather Service 6 | 7 | 8 | 9 | 10 | 11 | 12 |

13 | AI Weather Service 14 |

15 |
16 | 17 | 18 | 19 |
20 |

21 | Response: 22 |

23 |
24 | 25 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/ai-weather-application/src/main/resources/static/prompt.template: -------------------------------------------------------------------------------- 1 | Today is {today}. 2 | You will act as a meteorological expert who helps analyze and forecast weather. 3 | Given the following historical weather (in CSV format with header) of {city} over an entire year, please answer the questions and make predictions. 4 | Don't use any external data. 5 | 6 | {weatherHistory} -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/ai-weather-application/src/test/java/com/example/demo/AiWeatherApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class AiWeatherApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/media/01-question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/09-build-a-spring-ai-application-using-azure-openai/media/01-question.png -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/media/02-question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/09-build-a-spring-ai-application-using-azure-openai/media/02-question.png -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/media/03-question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/09-build-a-spring-ai-application-using-azure-openai/media/03-question.png -------------------------------------------------------------------------------- /spring/09-build-a-spring-ai-application-using-azure-openai/media/04-question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/java-on-aca-with-ai/16f838fb924b7481fd190b51eda9c51c65ca0d2c/spring/09-build-a-spring-ai-application-using-azure-openai/media/04-question.png -------------------------------------------------------------------------------- /spring/README.md: -------------------------------------------------------------------------------- 1 | # Build, Run and Monitor Intelligent Spring Java Apps on Azure Container Apps and Azure OpenAI 2 | 3 | This series of guides focus on building Java applications using Spring framwork and running them on Azure Container Apps. It also covers how to use Azure OpenAI to build AI applications. 4 | 5 | ## [00 - Prerequisites and Setup](00-setup-your-environment/README.md) 6 | 7 | Prerequisites and environment setup. 8 | 9 | ## [01 - Build a simple Java application](01-build-a-simple-java-application/README.md) 10 | 11 | Build the simplest possible Java application using the Spring Initializr. 12 | 13 | ## [02 - Create Managed Eureka Server for Spring](02-create-managed-eureka-server-for-spring/README.md) 14 | 15 | Create a [Spring Cloud Eureka Server](https://spring.io/projects/spring-cloud-netflix), that will be entirely managed and supported by Azure Container Apps, to be used by Spring Boot microservices. 16 | 17 | ## [03 - Create and configure Managed Config Server for Spring](03-create-and-configure-managed-config-server-for-spring/README.md) 18 | 19 | Create a managed [Spring Cloud Config Server](https://cloud.spring.io/spring-cloud-config) and configure it to access Git repository. 20 | 21 | ## [04 - Build a Spring Boot microservice using Spring Cloud features](04-build-a-spring-boot-microservice-using-spring-cloud-features/README.md) 22 | 23 | Build a Spring Boot microservice that is cloud-enabled: it uses a [Spring Cloud Eureka Server](https://spring.io/projects/spring-cloud-netflix) and a [Spring Cloud Config Server](https://cloud.spring.io/spring-cloud-config) which are both managed and supported by Azure Container Apps. 24 | 25 | ## [05 - Build a reactive Spring Boot microservice using Cosmos DB](05-build-a-reactive-spring-boot-microservice-using-cosmosdb/README.md) 26 | 27 | Build a reactive Spring Boot microservice, that uses the [Spring reactive stack](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) and is bound to a [Cosmos DB database](https://docs.microsoft.com/en-us/azure/cosmos-db/) in order to access a globally-distributed database with optimum performance. 28 | 29 | ## [06 - Build a Spring Boot microservice using MySQL](06-build-a-spring-boot-microservice-using-mysql/README.md) 30 | 31 | Build a classical Spring Boot application that uses JPA to access a [MySQL database managed by Azure](https://docs.microsoft.com/en-us/azure/mysql/). 32 | 33 | ## [07 - Build a Spring Cloud Gateway](07-build-a-spring-cloud-gateway/README.md) 34 | 35 | Build a [Spring Cloud Gateway](https://spring.io/projects/spring-cloud-gateway) to route HTTP requests to the correct Spring Boot microservices. 36 | 37 | ## [08 - Putting it all together, a complete microservice stack](08-putting-it-all-together-a-complete-microservice-stack/README.md) 38 | 39 | Use a front-end to access graphically our complete microservice stack. 40 | 41 | ## [09 - Build a Spring AI application using Azure OpenAI](09-build-a-spring-ai-application-using-azure-openai/README.md) 42 | 43 | Build an AI application that uses [Azure OpenAI Service](https://learn.microsoft.com/en-us/azure/ai-services/openai/) in order to analyze and forecast weather based on historical data. 44 | --------------------------------------------------------------------------------