{"id":18429137,"url":"https://github.com/openliberty/guide-cdi-intro","last_synced_at":"2026-03-15T21:11:00.499Z","repository":{"id":28643215,"uuid":"117571370","full_name":"OpenLiberty/guide-cdi-intro","owner":"OpenLiberty","description":"An introductory guide on how to use Contexts and Dependency Injection to manage and inject dependencies into microservices: https://openliberty.io/guides/cdi-intro.html","archived":false,"fork":false,"pushed_at":"2025-03-03T18:08:05.000Z","size":623,"stargazers_count":6,"open_issues_count":2,"forks_count":18,"subscribers_count":5,"default_branch":"prod","last_synced_at":"2025-03-22T21:51:10.300Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenLiberty.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-15T16:52:24.000Z","updated_at":"2025-03-03T18:08:10.000Z","dependencies_parsed_at":"2024-09-13T01:25:37.231Z","dependency_job_id":"d875b4a6-3a1c-4172-95e7-a83d4ecb128e","html_url":"https://github.com/OpenLiberty/guide-cdi-intro","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fguide-cdi-intro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fguide-cdi-intro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fguide-cdi-intro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fguide-cdi-intro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenLiberty","download_url":"https://codeload.github.com/OpenLiberty/guide-cdi-intro/tar.gz/refs/heads/prod","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247697944,"owners_count":20981277,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T05:15:59.286Z","updated_at":"2026-03-15T21:11:00.487Z","avatar_url":"https://github.com/OpenLiberty.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"// Copyright (c) 2017, 2025 IBM Corporation and others.\n// Licensed under Creative Commons Attribution-NoDerivatives\n// 4.0 International (CC BY-ND 4.0)\n//   https://creativecommons.org/licenses/by-nd/4.0/\n//\n// Contributors:\n//   IBM Corporation\n:projectid: cdi-intro\n:page-layout: guide-multipane\n:page-duration: 15 minutes\n:page-releasedate: 2018-03-09\n:page-guide-category: microprofile\n:page-essential: true\n:page-essential-order: 2\n:page-description: Learn how to use Contexts and Dependency Injection (CDI) to manage and inject dependencies into microservices.\n:guide-author: Open Liberty\n:page-tags: ['microprofile', 'jakarta-ee']\n:page-permalink: /guides/{projectid}\n:page-related-guides: ['rest-intro']\n:common-includes: https://raw.githubusercontent.com/OpenLiberty/guides-common/prod\n:source-highlighter: prettify\n:page-seo-title: Managing and injecting dependencies into Java microservices using Contexts and Dependency Injection (CDI)\n:page-seo-description: A getting started tutorial with examples of how to manage scopes and inject dependencies into Java microservices using Contexts and Dependency Injection (CDI).\n:figure-caption!:\n= Injecting dependencies into microservices\n\n[.hidden]\nNOTE: This repository contains the guide documentation source. To view the guide in published form, view it on the https://openliberty.io/guides/{projectid}.html[Open Liberty website].\n\nLearn how to use Contexts and Dependency Injection (CDI) to manage scopes and inject dependencies into microservices.\n\n== What you'll learn\n\nYou will learn how to use Contexts and Dependency Injection (CDI) to manage scopes and inject dependencies in a simple inventory management application.\n\nThe application that you will be working with is an `inventory` service, which stores the information about various JVMs that run on different systems. Whenever a request is made to the `inventory` service to retrieve the JVM system properties of a particular host, the `inventory` service communicates with the `system` service on that host to get these system properties. The system properties are then stored and returned.\n\nYou will use scopes to bind objects in this application to their well-defined contexts. CDI provides a variety of scopes for you to work with and while you will not use all of them in this guide, there is one for almost every scenario that you may encounter. Scopes are defined by using CDI annotations. You will also use dependency injection to inject one bean into another to make use of its functionalities. This enables you to inject the bean in its specified context without having to instantiate it yourself.\n\nThe implementation of the application and its services are provided for you in the `start/src` directory. The `system` service can be found in the `start/src/main/java/io/openliberty/guides/system` directory, and the `inventory` service can be found in the `start/src/main/java/io/openliberty/guides/inventory` directory. If you want to learn more about RESTful web services and how to build them, see https://openliberty.io/guides/rest-intro.html[Creating a RESTful web service^] for details about how to build the `system` service. The `inventory` service is built in a similar way.\n\n=== What is CDI?\n\nContexts and Dependency Injection (CDI) defines a rich set of complementary services that improve the application structure. The most fundamental services that are provided by CDI are contexts that bind the lifecycle of stateful components to well-defined contexts, and dependency injection that is the ability to inject components into an application in a typesafe way. With CDI, the container does all the daunting work of instantiating dependencies, and controlling exactly when and how these components are instantiated and destroyed.\n\n\n// =================================================================================================\n// Getting started\n// =================================================================================================\n\n[role='command']\ninclude::{common-includes}/gitclone.adoc[]\n\n[role='command']\ninclude::{common-includes}/twyb-intro-mvnw.adoc[]\n\nPoint your browser to the http://localhost:9080/inventory/systems[http://localhost:9080/inventory/systems^] URL.\nThis is the starting point of the `inventory` service and it displays the current contents of the inventory. As you might expect, these are empty because nothing is stored in the inventory yet. Next, point your browser to the http://localhost:9080/inventory/systems/localhost[http://localhost:9080/inventory/systems/localhost^] URL.\nYou see a result in JSON format with the system properties of your local JVM. When you visit this URL, these system properties are automatically stored in the inventory. Go back to http://localhost:9080/inventory/systems[http://localhost:9080/inventory/systems^]\nand you see a new entry for `localhost`. For simplicity, only the OS name and username are shown here for each host. You can repeat this process for your own hostname or any other machine that is running the `system` service.\n\n[role='command']\ninclude::{common-includes}/twyb-end-mvnw.adoc[]\n\n== Handling dependencies in the application\n\nYou will use CDI to inject dependencies into the inventory manager application and learn how to manage the life cycles of your objects.\n\n=== Managing scopes and contexts\n\nNavigate to the `start` directory to begin.\nifdef::cloud-hosted[]\n```bash\ncd /home/project/guide-cdi-intro/start\n```\nendif::[]\n\n[role='command']\ninclude::{common-includes}/devmode-mvnw-start.adoc[]\n\n[role=\"code_command hotspot\", subs=\"quotes\"]\n----\n#Create the `InventoryManager` class.#\n`src/main/java/io/openliberty/guides/inventory/InventoryManager.java`\n----\nInventoryManager.java\n[source, Java, linenums, role='code_column hide_tags=copyright']\n----\ninclude::finish/src/main/java/io/openliberty/guides/inventory/InventoryManager.java[]\n----\n\nThis bean contains two simple functions. The [hotspot=add file=0]`add()` function is for adding entries to the inventory. The [hotspot=list file=0]`list()` function is for listing all the entries currently stored in the inventory.\n\nThis bean must be persistent between all of the clients, which means multiple clients need to share the same instance. To achieve this by using CDI, you can simply add the [hotspot=ApplicationScoped file=0]`@ApplicationScoped` annotation onto the class.\n\nThis annotation indicates that this particular bean is to be initialized once per application. By making it application-scoped, the container ensures that the same instance of the bean is used whenever it is injected into the application.\n\n[role=\"code_command hotspot file=1\", subs=\"quotes\"]\n----\n#Create the `InventoryResource` class.#\n`src/main/java/io/openliberty/guides/inventory/InventoryResource.java`\n----\nInventoryResource.java\n[source, Java, linenums, role='code_column hide_tags=copyright']\n----\ninclude::finish/src/main/java/io/openliberty/guides/inventory/InventoryResource.java[]\n----\n\nThe inventory resource is a RESTful service that is served at the `inventory/systems` endpoint. \n\nAnnotating a class with the [hotspot=ApplicationScoped file=1]`@ApplicationScoped` annotation indicates that the bean is initialized once and is shared between all requests while the application runs.\n\nIf you want this bean to be initialized once for every request, you can annotate the class with the `@RequestScoped` annotation instead. With the `@RequestScoped` annotation, the bean is instantiated when the request is received and destroyed when a response is sent back to the client. A request scope is short-lived.\n\n=== Injecting a dependency\n\nRefer to the [hotspot=InventoryResource file=0]`InventoryResource` class you created above.\n\nThe [hotspot=inject hotspot=inject2 file=0]`@Inject` annotation indicates a dependency injection. You are injecting your `InventoryManager` and `SystemClient` beans into the `InventoryResource` class. This injects the beans in their specified context and makes all of their functionalities available without the need of instantiating them yourself. The injected bean `InventoryManager` can then be invoked directly through the [hotspot=managerAdd file=0]`manager.add(hostname, props)` and [hotspot=managerList file=0]`manager.list()` function calls. The injected bean `SystemClient` can be invoked through the [hotspot=properties file=0]`systemClient.getProperties(hostname)` function call.\n\nFinally, you have a client component [hotspot file=1]`SystemClient` that can be found in the `src/main/java/io/openliberty/guides/inventory/client` directory. This class communicates with the `system` service to retrieve the JVM system properties for a particular host that exposes them. This class also contains detailed Javadocs that you can read for reference.\n\nYour inventory application is now completed.\n\nInventoryResource.java\n[source, Java, linenums, role='code_column hide_tags=copyright']\n----\ninclude::finish/src/main/java/io/openliberty/guides/inventory/InventoryResource.java[]\n----\n\nSystemClient.java\n[source, Java, linenums, role='code_column hide_tags=copyright']\n----\ninclude::finish/src/main/java/io/openliberty/guides/inventory/client/SystemClient.java[]\n----\n\n// =================================================================================================\n// Running the application\n// =================================================================================================\n\n[role='command']\ninclude::{common-includes}/devmode-build.adoc[]\n\nYou can find the `system` and `inventory` services at the following URLs:\n\n* http://localhost:9080/system/properties[http://localhost:9080/system/properties^]\n* http://localhost:9080/inventory/systems/localhost[http://localhost:9080/inventory/systems/localhost^]\n* http://localhost:9080/inventory/systems[http://localhost:9080/inventory/systems^]\n\n// =================================================================================================\n// Testing\n// =================================================================================================\n\n== Testing the inventory application\n\nWhile you can test your application manually, you should rely on automated tests because they trigger a failure whenever a code change introduces a defect. Because the application is a RESTful web service application, you can use JUnit and the RESTful web service Client API to write tests. In testing the functionality of the application, the scopes and dependencies are being tested.\n\n[role=\"code_command hotspot\", subs=\"quotes\"]\n----\n#Create the `InventoryEndpointIT` class.#\n`src/test/java/it/io/openliberty/guides/inventory/InventoryEndpointIT.java`\n----\n\nInventoryEndpointIT.java\n[source, Java, linenums, role='code_column hide_tags=copyright']\n----\ninclude::finish/src/test/java/it/io/openliberty/guides/inventory/InventoryEndpointIT.java[]\n----\n\nThe [hotspot=BeforeAll file=0]`@BeforeAll` annotation is placed on a method that runs before any of the test cases. In this case, the [hotspot=oneTimeSetup file=0]`oneTimeSetup()` method retrieves the port number for the Open Liberty and builds a base URL string that is used throughout the tests.\n\nThe [hotspot=BeforeEach file=0]`@BeforeEach` and [hotspot=AfterEach file=0]`@AfterEach` annotations are placed on methods that run before and after every test case. These methods are generally used to perform any setup and teardown tasks. In this case, the [hotspot=setup file=0]`setup()` method creates a JAX-RS client, which makes HTTP requests to the `inventory` service. The [hotspot=teardown file=0]`teardown()` method simply destroys this client instance.\n\nSee the following descriptions of the test cases:\n\n* [hotspot=testHostRegistration file=0]`testHostRegistration()` verifies that a host is correctly added to the inventory.\n\n* [hotspot=testSystemPropertiesMatch file=0]`testSystemPropertiesMatch()` verifies that the JVM system properties returned by the `system` service match the ones stored in the `inventory` service.\n\n* [hotspot=testUnknownHost file=0]`testUnknownHost()` verifies that an unknown host or a host that does not expose their JVM system properties is correctly handled as an error.\n\nTo force these test cases to run in a particular order, annotate your [hotspot file=0]`InventoryEndpointIT` test class with the [hotspot=TestMethodOrder file=0]`@TestMethodOrder(OrderAnnotation.class)` annotation. [hotspot=TestMethodOrder file=0]`OrderAnnotation.class` runs test methods in numerical order, according to the values specified in the [hotspot=Order1 hotspot=Order2 hotspot=Order3 file=0]`@Order` annotation. You can also create a custom `MethodOrderer` class or use built-in `MethodOrderer` implementations, such as `OrderAnnotation.class`, `Alphanumeric.class`, or `Random.class`. Label your test cases with the [hotspot=Test1 hotspot=Test2 hotspot=Test3 file=0]`@Test` annotation so that they automatically run when your test class runs.\n\nFinally, the [hotspot file=1]`src/test/java/it/io/openliberty/guides/system/SystemEndpointIT.java` file is included for you to test the basic functionality of the `system` service. If a test failure occurs, then you might have introduced a bug into the code.\n\nSystemEndpointIT.java\n[source, Java, linenums, role='code_column hide_tags=copyright']\n----\ninclude::finish/src/test/java/it/io/openliberty/guides/system/SystemEndpointIT.java[]\n----\n\n// =================================================================================================\n// Running the tests\n// =================================================================================================\n\n[role='command']\ninclude::{common-includes}/devmode-test.adoc[]\n\nIf the tests pass, you see a similar output to the following example:\n\n[source, role='no_copy']\n----\n-------------------------------------------------------\n T E S T S\n-------------------------------------------------------\nRunning it.io.openliberty.guides.system.SystemEndpointIT\nTests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.99 sec - in it.io.openliberty.guides.system.SystemEndpointIT\nRunning it.io.openliberty.guides.inventory.InventoryEndpointIT\n[err] Runtime exception: RESTEASY004655: Unable to invoke request: java.net.UnknownHostException: badhostname: nodename nor servname provided, or not known\nTests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.325 sec - in it.io.openliberty.guides.inventory.InventoryEndpointIT\n\nResults :\n\nTests run: 4, Failures: 0, Errors: 0, Skipped: 0\n----\n\nThe error messages are expected and result from a request to a bad or an unknown hostname. This request is made in the `testUnknownHost()` test from the `InventoryEndpointIT` integration test.\n\nTo see whether the tests detect a failure, change the [hotspot=endpoint file=0]`endpoint` for the `inventory` service in the [hotspot file=0]`src/main/java/io/openliberty/guides/inventory/InventoryResource.java` file to something else. Then, run the tests again to see that a test failure occurs.\n\nInventoryResource.java\n[source, Java, linenums, role='code_column hide_tags=copyright']\n----\ninclude::finish/src/main/java/io/openliberty/guides/inventory/InventoryResource.java[]\n----\n\n[role='command']\ninclude::{common-includes}/devmode-quit.adoc[]\n\n== Great work! You're done!\n\nYou just used CDI services in Open Liberty to build a simple inventory application.\n\ninclude::{common-includes}/attribution.adoc[subs=\"attributes\"]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenliberty%2Fguide-cdi-intro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenliberty%2Fguide-cdi-intro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenliberty%2Fguide-cdi-intro/lists"}