{"id":15924101,"url":"https://github.com/ericglau/demo-devex","last_synced_at":"2025-08-31T03:35:21.395Z","repository":{"id":116634942,"uuid":"190801686","full_name":"ericglau/demo-devex","owner":"ericglau","description":"Demo of Liberty dev mode","archived":false,"fork":false,"pushed_at":"2020-10-13T13:45:32.000Z","size":755,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-09T02:15:43.822Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/ericglau.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-07T20:01:16.000Z","updated_at":"2019-08-28T20:07:27.000Z","dependencies_parsed_at":null,"dependency_job_id":"04732ee7-44e3-4d0f-93a8-7e21a02f7233","html_url":"https://github.com/ericglau/demo-devex","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/ericglau%2Fdemo-devex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericglau%2Fdemo-devex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericglau%2Fdemo-devex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericglau%2Fdemo-devex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ericglau","download_url":"https://codeload.github.com/ericglau/demo-devex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247005410,"owners_count":20868019,"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-10-06T21:20:22.953Z","updated_at":"2025-04-03T12:46:00.994Z","avatar_url":"https://github.com/ericglau.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# liberty:dev Demo\n\n## Overview of liberty:dev mode\n* hot deployment with background compilation mode so that added pom dependencies, java, resource, and configuration file changes are picked up while your server is running\n* built on top of the [ci.maven](https://github.com/OpenLiberty/ci.maven) plugin\n\n### Documentation\nhttps://github.com/OpenLiberty/ci.maven/blob/master/docs/dev.md\n\n### Specific functionalities:\n* default server starts on `mvn liberty:dev` and stops on ctl-c\n* java source file changes will be picked up dynamically (any java files in the `src/main/java` and `src/test/java` directory)\n* server configuration file changes (any files in the config directory indicated in the pom.xml) will be picked up dynamically \n* resource file changes (any files in the `src/main/resources` directory)\n* unit and integration tests run on a seperate thread after every successful compile  \n* feature dependency changes in pom.xml are picked up dynamically, triggers feature installation\n* debug port opened by default at port: 7777, works with any debugger\n\n## How to try out liberty:dev mode\n1. Clone this repo.\n\n2. Run `mvn liberty:dev` to start liberty:dev mode\n\n3. Enable the `microprofile-health-api` dependency in the pom.xml.  Notice that the new dependency gets automatically installed.\n\n4. Add `mpHealth-2.0` feature to the 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\u003e5. Create the src/main/java/io/openliberty/guides/system/SystemLivenessCheck.java class.  Changes are reflected in the http://localhost:9080/health endpoint.  \u003c/summary\u003e\n\n```\npackage io.openliberty.guides.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                                  .state(memUsed \u003c memMax * 0.9).build();\n    }\n    \n}\n```\n\u003c/details\u003e\n\n\n6. 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\u003e7. Create the src/main/java/io/openliberty/guides/system/SystemReadinessCheck.java class.  Changes are reflected in the http://localhost:9080/health endpoint. \u003c/summary\u003e\n\n```\npackage io.openliberty.guides.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\n8. Change the `io_openliberty_guides_system_inMaintenance` property in `resources/CustomConfigSource.json` to true.  Changes are reflected in the http://localhost:9080/health endpoint.\n\n\n9. Change the `config_ordinal` value to 800 in the `src/main/resources/META-INF/microprofile-config.properties`. Changes are reflected in the http://localhost:9080/health endpoint. Undo steps 8 and 9 afterwards.\n\n\n10. 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\u003cdetails\u003e\n    \u003csummary\u003e11. Create the src/test/java/io/openliberty/guides/health/HealthEndpointIT.java class as an integration test. Press Enter in the console. The tests are run and should pass. \u003c/summary\u003e\n    \n```\npackage io.openliberty.guides.health;\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 port = System.getProperty(\"liberty.http.port\", \"9080\");\n        baseUrl = \"http://localhost:\" + 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\n12. Connect to the debug port 7777 with a debugger.\n\n13. When you are done use ctl-c to terminate liberty:dev mode and stop your server\n\n## How to use liberty:dev in an existing project\n\n### (Optional) To Build from Source\n1. Clone [ci.ant](https://github.com/OpenLiberty/ci.ant): `git clone https://github.com/OpenLiberty/ci.ant.git`\n2. Clone [ci.common](https://github.com/OpenLiberty/ci.common): `git clone https://github.com/OpenLiberty/ci.common.git`\n3. Clone [ci.maven](https://github.com/OpenLiberty/ci.maven): `git clone https://github.com/OpenLiberty/ci.maven.git`\n4. Build ci.ant `mvn clean install -DskipTests`, then ci.common `mvn clean install`, and then ci.maven `mvn clean install` to generate `3.0-M2-SNAPSHOT` of the liberty-maven-plugin\n\nOr in one command from an empty directory:\n```\ngit clone https://github.com/OpenLiberty/ci.ant.git \u0026\u0026 cd ci.ant \u0026\u0026 mvn clean install -DskipTests \u0026\u0026 cd .. \u0026\u0026 git clone https://github.com/OpenLiberty/ci.common.git \u0026\u0026 cd ci.common \u0026\u0026 mvn clean install \u0026\u0026 cd .. \u0026\u0026 git clone https://github.com/OpenLiberty/ci.maven.git \u0026\u0026 cd ci.maven \u0026\u0026 mvn clean install \u0026\u0026 cd ..\n```\n\n### To Use \n1. Do one of the following:  \n   a) Perform the steps in the \"To Build from Source\", then in your pom.xml specify the following for the liberty-maven-plugin:\n```\n\u003cplugin\u003e\n    \u003cgroupId\u003eio.openliberty.tools\u003c/groupId\u003e\n    \u003cartifactId\u003eliberty-maven-plugin\u003c/artifactId\u003e\n    \u003cversion\u003e3.0-M2-SNAPSHOT\u003c/version\u003e\n\u003c/plugin\u003e\n```\n*or*  \n   b) In your pom.xml specify the following for the liberty-maven-plugin, which will use the milestone release from Maven Central  \ne.g.  \n```\n\u003cplugin\u003e\n    \u003cgroupId\u003eio.openliberty.tools\u003c/groupId\u003e\n    \u003cartifactId\u003eliberty-maven-plugin\u003c/artifactId\u003e\n    \u003cversion\u003e3.0-M2\u003c/version\u003e\n\u003c/plugin\u003e\n```\n2. Start liberty:dev mode with `mvn liberty:dev`\n3. Make any code changes to java source files, resource files or configuration files and see that the changes are picked up dynamically while the server is running\n4. Attach a debugger, by default the liberty:dev mode allows for a debugger to attach to port: 7777.  Note: this will not work if you have a jvmOptions property set in your pom.xml \n5. When you are done use 'ctl-c' to terminate liberty:dev mode and stop your server\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericglau%2Fdemo-devex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fericglau%2Fdemo-devex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericglau%2Fdemo-devex/lists"}