{"id":18429201,"url":"https://github.com/openliberty/demo-devmode","last_synced_at":"2025-04-07T17:32:56.009Z","repository":{"id":38441491,"uuid":"208326011","full_name":"OpenLiberty/demo-devmode","owner":"OpenLiberty","description":null,"archived":false,"fork":false,"pushed_at":"2022-11-15T00:32:24.000Z","size":549,"stargazers_count":9,"open_issues_count":1,"forks_count":10,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-22T21:51:11.180Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-09-13T18:43:36.000Z","updated_at":"2024-08-18T07:44:11.000Z","dependencies_parsed_at":"2023-01-21T02:16:13.162Z","dependency_job_id":null,"html_url":"https://github.com/OpenLiberty/demo-devmode","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fdemo-devmode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fdemo-devmode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fdemo-devmode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenLiberty%2Fdemo-devmode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenLiberty","download_url":"https://codeload.github.com/OpenLiberty/demo-devmode/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247697964,"owners_count":20981278,"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:16:12.795Z","updated_at":"2025-04-07T17:32:55.626Z","avatar_url":"https://github.com/OpenLiberty.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Liberty dev mode demo\n\n### Quick links\n[Maven dev mode documentation](https://github.com/OpenLiberty/ci.maven/blob/master/docs/dev.md)  \n[Gradle dev mode documentation](https://github.com/OpenLiberty/ci.gradle/blob/master/docs/libertyDev.md)  \n[Open Liberty Tools VS Code extension (optional)](https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext)  \n[Open Liberty Tools IntelliJ extension (optional)](https://plugins.jetbrains.com/plugin/14856-open-liberty-tools)\n\n## Demo scenario\n\n### Hot deployment\n\n1. Clone this repo.\n\n2. Start dev mode:\n    - Maven: `mvn liberty:dev`\n    - Gradle: `gradle libertyDev`\n\n3. Add `mpHealth-3.1` feature to `src/main/liberty/config/server.xml`. You can now access the http://localhost:9080/health endpoint (though it's just an empty array).\n\n\u003cdetails\u003e\n    \u003csummary\u003e4. Create the src/main/java/io/openliberty/sample/system/SystemLivenessCheck.java class.  Changes are reflected in the http://localhost:9080/health endpoint.  \u003c/summary\u003e\n\n```java\npackage io.openliberty.sample.system;\n\nimport javax.enterprise.context.ApplicationScoped;\n\nimport java.lang.management.MemoryMXBean;\nimport java.lang.management.ManagementFactory;\n\nimport org.eclipse.microprofile.health.Liveness;\nimport org.eclipse.microprofile.health.HealthCheck;\nimport org.eclipse.microprofile.health.HealthCheckResponse;\n\n@Liveness\n@ApplicationScoped\npublic class SystemLivenessCheck implements HealthCheck {\n\n    @Override\n    public HealthCheckResponse call() {\n        MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();\n        long memUsed = memBean.getHeapMemoryUsage().getUsed();\n        long memMax = memBean.getHeapMemoryUsage().getMax();\n  \n        return HealthCheckResponse.named(\n            SystemResource.class.getSimpleName() + \" liveness check\")\n                                  .withData(\"memory used\", memUsed)\n                                  .withData(\"memory max\", memMax)\n                                  .status(memUsed \u003c memMax * 0.9).build();\n    }\n    \n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003e5. Create the src/main/java/io/openliberty/sample/system/SystemReadinessCheck.java class.  Changes are reflected in the http://localhost:9080/health endpoint. \u003c/summary\u003e\n\n```java\npackage io.openliberty.sample.system;\n\nimport javax.enterprise.context.ApplicationScoped;\n\nimport javax.inject.Inject;\nimport javax.inject.Provider;\n\nimport org.eclipse.microprofile.config.inject.ConfigProperty;\nimport org.eclipse.microprofile.health.Readiness;\nimport org.eclipse.microprofile.health.HealthCheck;\nimport org.eclipse.microprofile.health.HealthCheckResponse;\nimport org.eclipse.microprofile.health.HealthCheckResponseBuilder;\n\n@Readiness\n@ApplicationScoped\npublic class SystemReadinessCheck implements HealthCheck {\n\n    @Inject\n    @ConfigProperty(name = \"io_openliberty_guides_system_inMaintenance\")\n    Provider\u003cString\u003e inMaintenance;\n\t\n    @Override\n    public HealthCheckResponse call() {\n        HealthCheckResponseBuilder builder = HealthCheckResponse.named(\n\t\tSystemResource.class.getSimpleName() + \" readiness check\");\n        if (inMaintenance != null \u0026\u0026 inMaintenance.get().equalsIgnoreCase(\"true\")) {\n            return builder.withData(\"services\", \"not available\").down().build();\n        }\n        return builder.withData(\"services\", \"available\").up().build();\n    }\n    \n}\n```\n\u003c/details\u003e\n\n6. Change the `io_openliberty_guides_system_inMaintenance` variable in `src/main/liberty/config/server.xml` to `true`.  Changes are reflected in the http://localhost:9080/health endpoint.  Undo this afterwards.\n\n7. Make changes to the `src/main/webapp/index.html` (or any other webapp files). Changes are reflected on the home page http://localhost:9080/.\n\n### Hot testing\n\n1. Go to the console where you started dev mode, and press Enter.  The integration tests are run on a separate thread while dev mode is still active.\n\n\u003cdetails\u003e\n    \u003csummary\u003e2. Create the src/test/java/it/io/openliberty/sample/HealthEndpointIT.java class as an integration test. Notice the \"liberty.hostname\" and \"liberty.http.port\" system properties which are provided by dev mode when running integration tests. Press Enter in the console to run the tests. They should pass. \u003c/summary\u003e\n    \n```java\npackage it.io.openliberty.sample;\n\nimport static org.junit.Assert.assertEquals;\n\nimport javax.json.JsonObject;\nimport javax.ws.rs.client.Client;\nimport javax.ws.rs.client.ClientBuilder;\nimport javax.ws.rs.core.Response;\n\nimport org.apache.cxf.jaxrs.provider.jsrjsonp.JsrJsonpProvider;\nimport org.junit.After;\nimport org.junit.Before;\nimport org.junit.BeforeClass;\nimport org.junit.Test;\n\npublic class HealthEndpointIT {\n    \n    private static String baseUrl;\n    private static final String HEALTH_ENDPOINT = \"/health\";\n    private static final String LIVENESS_ENDPOINT = \"/health/live\";\n    private static final String READINESS_ENDPOINT = \"/health/ready\";\n    \n    private Client client;\n    private Response response;\n    \n    @BeforeClass\n    public static void oneTimeSetup() {\n        String hostname = System.getProperty(\"liberty.hostname\", \"localhost\");\n        String port = System.getProperty(\"liberty.http.port\", \"9080\");\n        baseUrl = \"http://\" + hostname + \":\" + port + \"/\";\n    }\n    \n    @Before\n    public void setup() {\n        response = null;\n        client = ClientBuilder.newClient();\n        client.register(JsrJsonpProvider.class);\n    }\n    \n    @After\n    public void teardown() {\n        response.close();\n        client.close();\n    }\n\n    @Test\n    public void testHealthEndpoint() {\n        String healthURL = baseUrl + HEALTH_ENDPOINT;\n        response = this.getResponse(baseUrl + HEALTH_ENDPOINT);\n        this.assertResponse(healthURL, response);\n        \n        JsonObject healthJson = response.readEntity(JsonObject.class);\n        String expectedOutcome = \"UP\";\n        String actualOutcome = healthJson.getString(\"status\");\n        assertEquals(\"Application should be healthy\", expectedOutcome, actualOutcome);\n       \n        JsonObject healthCheck = healthJson.getJsonArray(\"checks\").getJsonObject(0);\n        String healthCheckName = healthCheck.getString(\"name\");\n        actualOutcome = healthCheck.getString(\"status\");\n        assertEquals(healthCheckName + \" wasn't healthy\", expectedOutcome, actualOutcome);\n\n        healthCheck = healthJson.getJsonArray(\"checks\").getJsonObject(1);\n        healthCheckName = healthCheck.getString(\"name\");\n        actualOutcome = healthCheck.getString(\"status\");\n        assertEquals(healthCheckName + \" wasn't healthy\", expectedOutcome, actualOutcome);\n    }\n\n    @Test\n    public void testLivenessEndpoint() {\n        String livenessURL = baseUrl + LIVENESS_ENDPOINT;\n        response = this.getResponse(baseUrl + LIVENESS_ENDPOINT);\n        this.assertResponse(livenessURL, response);\n        \n        JsonObject healthJson = response.readEntity(JsonObject.class);\n        String expectedOutcome = \"UP\";\n        String actualOutcome = healthJson.getString(\"status\");\n        assertEquals(\"Applications liveness check passed\", expectedOutcome, actualOutcome);\n    }\n\n    @Test\n    public void testReadinessEndpoint() {\n        String readinessURL = baseUrl + READINESS_ENDPOINT;\n        response = this.getResponse(baseUrl + READINESS_ENDPOINT);\n        this.assertResponse(readinessURL, response);\n        \n        JsonObject healthJson = response.readEntity(JsonObject.class);\n        String expectedOutcome = \"UP\";\n        String actualOutcome = healthJson.getString(\"status\");\n        assertEquals(\"Applications readiness check passed\", expectedOutcome, actualOutcome);\n    }\n   \n    private Response getResponse(String url) {\n        return client.target(url).request().get();\n    }\n\n    private void assertResponse(String url, Response response) {\n        assertEquals(\"Incorrect response code from \" + url, 200, response.getStatus());\n    }\n\n}\n```\n\u003c/details\u003e\n\n3. Stop dev mode by pressing Ctrl-C in the console.\n\n4. Run dev mode with hot testing enabled.\n    - Maven: `mvn liberty:dev -DhotTests`\n    - Gradle: `gradle libertyDev --hotTests`\n\n5. Notice tests are run immediately after dev mode starts up.\n\n6. In `src/main/java/io/openliberty/sample/system/SystemResource.java`, change the annotation `@Path(\"/properties\")` to `@Path(\"/properties2\")`.\n\n7. Notice tests are run automatically after the source change, and a test fails because the endpoint path is wrong.\n\n8. Revert the annotation back to `@Path(\"/properties\")`.\n\n9. Notice tests are run automatically and pass.\n\n### Hot debugging\n\n1. In `src/main/java/io/openliberty/sample/system/SystemLivenessCheck.java`, set a breakpoint inside the `call()` method.\n\n2. Attach your IDE's debugger to port `7777`.  \nFor example, in VS Code, click `Debug` \u003e `Add Configuration...` \u003e `Java: Attach` \u003e set `\"port\": \"7777\"`.  Then `View` \u003e `Debug` \u003e select `Debug (Attach)`, then press the arrow icon to start debugging.\n\n3. In your browser, go to http://localhost:9080/health.\n\n4. Notice your IDE pauses at the breakpoint that you set, allowing you to debug.\n\n5. Disconnect the debugger.\n\n6. When you are done, press Ctrl-C in the console to terminate dev mode and stop your server.\n\n## VS Code extension\n\nThe [Open Liberty Tools for VS Code](https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext) extension is an IDE specific extension that lets you interact with dev mode through menu options as an alternative to using the console.\n\n1. In VS Code, go to the Extensions view (`View` \u003e `Extensions`).\n\n2. Search for `Open Liberty Tools`.\n\n3. Click `Install`.\n\n4. Go to the Explorer view (`View` \u003e `Explorer`).\n\n5. In the side bar, `Liberty Dev Dashboard` shows your Liberty dev projects.\n\n6. Right-click your project to start, stop, and interact with dev mode.\n\n\u003cimg src=\"libertydev_vscode.png\" width=\"50%\" height=\"50%\" title=\"Open Liberty Tools VS Code extension\"\u003e\n\n## IntelliJ extension\n\nThe [Open Liberty Tools for IntelliJ](https://plugins.jetbrains.com/plugin/14856-open-liberty-tools) extension is an IDE specific extension lets you interact with dev mode through menu options as an alternative to using the console.\n\n1. In IntelliJ, go to the Plugins Marketplace (`Settings` \u003e `Plugins` \u003e `Marketplace`).\n\n2. Search for `Open Liberty Tools`.\n\n3. Click `Install`.\n\n4. In the right side bar, `Liberty Dev Dashboard` shows your Liberty dev projects.\n\n6. Right-click your project name or select a task from the drop-down list to start, stop, and interact with dev mode.\n\n\u003cimg src=\"olt_intellij.png\" width=\"50%\" height=\"50%\" title=\"Open Liberty Tools VS Code extension\"\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenliberty%2Fdemo-devmode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenliberty%2Fdemo-devmode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenliberty%2Fdemo-devmode/lists"}