Skip to content

[issue-325] - Add tests to verify that HealthCheckResponse has a name when built as recommended on the producer side#326

Open
fabiobrz wants to merge 2 commits intomicroprofile:mainfrom
fabiobrz:issue-325
Open

[issue-325] - Add tests to verify that HealthCheckResponse has a name when built as recommended on the producer side#326
fabiobrz wants to merge 2 commits intomicroprofile:mainfrom
fabiobrz:issue-325

Conversation

@fabiobrz
Copy link

@fabiobrz fabiobrz commented Mar 13, 2024

SSIA.

Fixes #325

TCKs are running fine, see last comment

Copy link
Member

@xstefank xstefank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @fabiobrz for your PR. But I need to request some changes. I don't think generating the name should be our solution to null names. I don't see the point of having random name since it won't (probably) give value to user when the health checks is first invoked. So then when then need to restart the app to add the name, I think it would be better to throw and exception (possibly on startup when we detect null name) to prevent app from running.

Also in every case, this will require adjustment in the specification text. I'm willing to hop on a quick call if you want to discuss this case in more detail. (/cc @pgunapal I would like to hear you opinion too).

@fabiobrz
Copy link
Author

Thanks @fabiobrz for your PR. But I need to request some changes. I don't think generating the name should be our solution to null names. I don't see the point of having random name since it won't (probably) give value to user when the health checks is first invoked. So then when then need to restart the app to add the name, I think it would be better to throw and exception (possibly on startup when we detect null name) to prevent app from running.

Yeah, you might be right in here, thanks, fixing.

Also in every case, this will require adjustment in the specification text. I'm willing to hop on a quick call if you want to discuss this case in more detail. (/cc @pgunapal I would like to hear you opinion too).

Correct, the spec text should be adjusted. I am glad to learn about this, so feel free to get in touch, and thanks for your review!

fabiobrz added a commit to fabiobrz/smallrye-health that referenced this pull request Mar 13, 2024
@fabiobrz fabiobrz changed the title [issue-325] - Make sure HealthCheckResponse is given a name when invoked through ::ctor, ::up, and ::down [issue-325] - Add tests to verify that HealthCHeckResponse has a name when built as recommended on the producer side Mar 15, 2024
@pgunapal
Copy link
Contributor

I agree with @xstefank, It wouldn't make sense to randomly generate a name for a Health check with no-name.
We should throw an exception if we detect a health check without a name.

+1 on updating the specification, with this detail.

@fabiobrz fabiobrz changed the title [issue-325] - Add tests to verify that HealthCHeckResponse has a name when built as recommended on the producer side [issue-325] - Add tests to verify that HealthCheckResponse has a name when built as recommended on the producer side Mar 20, 2025
@fabiobrz fabiobrz force-pushed the issue-325 branch 2 times, most recently from 3c65f11 to ed14991 Compare June 29, 2025 14:35
@fabiobrz
Copy link
Author

fabiobrz commented Jun 29, 2025

Hi @xstefank, @pgunapal - I am back in order to update this PR and the related issue for resolution.

The only thing we can do here, as agreed the last time we discussed this, is to add tests to the TCK - which is what I've done - for it to be aligned with the related spec requirements.

The spec codebase itself cannot enforce the requirement since it clearly states that application level code is expected to use static methods to build the response and spec implementors are required to provide the HealthCheckResponseBuilder.

In order to verify that the new TCK tests are executed, I've built a snapshot from the PR branch, then I let the WildFly integration test suite run them, and they passed, see a GitHub action execution which is based on a workflow that I've created for this: https://github.com/fabiobrz/wildfly/actions/runs/15956712879/job/45003958341

Specifically, we can see from the server logs generated by the above linked job execution, that the smallrye-health implementation is aligned already with the spec requirement which mandates the name to be not null or empty:

...
2025-06-29 15:34:09,255 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-8) WFLYSRV0027: Starting deployment of "NullNameHealthCheckResponseTest.war" (runtime-name: "NullNameHealthCheckResponseTest.war")
2025-06-29 15:34:09,556 INFO  [org.jboss.weld.deployer] (MSC service thread 1-7) WFLYWELD0003: Processing weld deployment NullNameHealthCheckResponseTest.war
2025-06-29 15:34:09,822 INFO  [org.wildfly.extension.microprofile.health.smallrye] (MSC service thread 1-5) WFLYMPHEALTH0007: The deployment NullNameHealthCheckResponseTest.war configuration has specified that default MicroProfile Health procedures should be disabled; server-wide procedures will be disabled.
2025-06-29 15:34:09,832 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 10) WFLYUT0021: Registered web context: '/NullNameHealthCheckResponseTest' for server 'default-server'
2025-06-29 15:34:09,849 INFO  [org.jboss.as.server] (management-handler-thread - 2) WFLYSRV0010: Deployed "NullNameHealthCheckResponseTest.war" (runtime-name : "NullNameHealthCheckResponseTest.war")
2025-06-29 15:34:09,876 ERROR [org.wildfly.extension.microprofile.health.smallrye] (management I/O-2) Error processing Health Checks: java.lang.IllegalArgumentException: Health Check contains an invalid name. Can not be null or empty.
	at io.smallrye.health@4.2.0//io.smallrye.health.ResponseBuilder.build(ResponseBuilder.java:59)
	at org.eclipse.microprofile.health.api@4.1-SNAPSHOT//org.eclipse.microprofile.health.HealthCheckResponse.up(HealthCheckResponse.java:141)
	at deployment.NullNameHealthCheckResponseTest.war//org.eclipse.microprofile.health.tck.deployment.NullNameCheck.call(NullNameCheck.java:35)
	at deployment.NullNameHealthCheckResponseTest.war//org.eclipse.microprofile.health.tck.deployment.NullNameCheck$Proxy$_$$_WeldClientProxy.call(Unknown Source)
	at org.wildfly.extension.microprofile.health-smallrye@37.0.0.Final-SNAPSHOT//org.wildfly.extension.microprofile.health.MicroProfileHealthReporter.jsonObject(MicroProfileHealthReporter.java:250)
	at org.wildfly.extension.microprofile.health-smallrye@37.0.0.Final-SNAPSHOT//org.wildfly.extension.microprofile.health.MicroProfileHealthReporter.fillCheck(MicroProfileHealthReporter.java:237)
	at org.wildfly.extension.microprofile.health-smallrye@37.0.0.Final-SNAPSHOT//org.wildfly.extension.microprofile.health.MicroProfileHealthReporter.processChecks(MicroProfileHealthReporter.java:226)
	at org.wildfly.extension.microprofile.health-smallrye@37.0.0.Final-SNAPSHOT//org.wildfly.extension.microprofile.health.MicroProfileHealthReporter.getHealth(MicroProfileHealthReporter.java:199)
	at org.wildfly.extension.microprofile.health-smallrye@37.0.0.Final-SNAPSHOT//org.wildfly.extension.microprofile.health.MicroProfileHealthReporter.getHealth(MicroProfileHealthReporter.java:189)
	at org.wildfly.extension.microprofile.health-smallrye@37.0.0.Final-SNAPSHOT//org.wildfly.extension.microprofile.health.MicroProfileHealthReporter.getStartup(MicroProfileHealthReporter.java:185)
	at org.wildfly.extension.microprofile.health-smallrye@37.0.0.Final-SNAPSHOT//org.wildfly.extension.microprofile.health.MicroProfileHealthContextService$HealthCheckHandler.handleRequest(MicroProfileHealthContextService.java:82)
	at org.wildfly.extension.health@37.0.0.Final-SNAPSHOT//org.wildfly.extension.health.HealthContextService$HealthCheckHandler.handleRequest(HealthContextService.java:108)
	at org.jboss.as.domain-http-interface@29.0.0.Beta6//org.jboss.as.domain.http.server.security.RealmReadinessHandler.handleRequest(RealmReadinessHandler.java:34)
	at org.jboss.as.domain-http-interface@29.0.0.Beta6//org.jboss.as.domain.http.server.security.ServerErrorReadinessHandler.handleRequest(ServerErrorReadinessHandler.java:22)
	at io.undertow.core@2.3.18.Final//io.undertow.server.handlers.PathHandler.handleRequest(PathHandler.java:104)
	at io.undertow.core@2.3.18.Final//io.undertow.server.handlers.ChannelUpgradeHandler.handleRequest(ChannelUpgradeHandler.java:212)
	at io.undertow.core@2.3.18.Final//io.undertow.server.handlers.cache.CacheHandler.handleRequest(CacheHandler.java:92)
	at io.undertow.core@2.3.18.Final//io.undertow.server.handlers.error.SimpleErrorPageHandler.handleRequest(SimpleErrorPageHandler.java:78)
	at io.undertow.core@2.3.18.Final//io.undertow.server.handlers.CanonicalPathHandler.handleRequest(CanonicalPathHandler.java:49)
	at org.jboss.as.domain-http-interface@29.0.0.Beta6//org.jboss.as.domain.http.server.ManagementHttpRequestHandler.handleRequest(ManagementHttpRequestHandler.java:40)
	at org.jboss.as.domain-http-interface@29.0.0.Beta6//org.jboss.as.domain.http.server.cors.CorsHttpHandler.handleRequest(CorsHttpHandler.java:60)
	at org.jboss.as.domain-http-interface@29.0.0.Beta6//org.jboss.as.domain.http.server.ManagementHttpServer$UpgradeFixHandler.handleRequest(ManagementHttpServer.java:683)
	at io.undertow.core@2.3.18.Final//io.undertow.server.Connectors.executeRootHandler(Connectors.java:395)
	at io.undertow.core@2.3.18.Final//io.undertow.server.protocol.http.HttpReadListener.handleEventWithNoRunningRequest(HttpReadListener.java:265)
	at io.undertow.core@2.3.18.Final//io.undertow.server.protocol.http.HttpReadListener.handleEvent(HttpReadListener.java:136)
	at io.undertow.core@2.3.18.Final//io.undertow.server.protocol.http.HttpOpenListener.handleEvent(HttpOpenListener.java:162)
	at io.undertow.core@2.3.18.Final//io.undertow.server.protocol.http.HttpOpenListener.handleEvent(HttpOpenListener.java:100)
	at io.undertow.core@2.3.18.Final//io.undertow.server.protocol.http.HttpOpenListener.handleEvent(HttpOpenListener.java:57)
	at org.jboss.xnio@3.8.16.Final//org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
	at org.jboss.xnio@3.8.16.Final//org.xnio.ChannelListeners$10.handleEvent(ChannelListeners.java:291)
	at org.jboss.xnio@3.8.16.Final//org.xnio.ChannelListeners$10.handleEvent(ChannelListeners.java:286)
	at org.jboss.xnio@3.8.16.Final//org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
	at org.jboss.xnio.nio@3.8.16.Final//org.xnio.nio.QueuedNioTcpServer2.acceptTask(QueuedNioTcpServer2.java:178)
	at org.jboss.xnio.nio@3.8.16.Final//org.xnio.nio.WorkerThread.safeRun(WorkerThread.java:624)
	at org.jboss.xnio.nio@3.8.16.Final//org.xnio.nio.WorkerThread.run(WorkerThread.java:491)
...

I think this is ready to go in. Could you please review the changes again?

@fabiobrz fabiobrz requested a review from xstefank June 29, 2025 15:37
@fabiobrz fabiobrz marked this pull request as ready for review June 29, 2025 15:40
Copy link
Member

@xstefank xstefank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabiobrz looks good, just fix the license headers.

Also please update the text so this is clearly stated as a requirement for the implementations. Because if we merge it like this, this will be hidden until the TCK is ran.

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2021 Contributors to the Eclipse Foundation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks.

fabiobrz added 2 commits June 30, 2025 13:51
…HealthCheckResponse name is null or empty string
…st verify that a consistent name is provided when constructing a HealthCheckResponse instance, and fail accordingly if it is not
@fabiobrz
Copy link
Author

@fabiobrz looks good, just fix the license headers.

Also please update the text so this is clearly stated as a requirement for the implementations. Because if we merge it like this, this will be hidden until the TCK is ran.

Thanks @xstefank - everything should be fixed now.

@fabiobrz fabiobrz requested a review from xstefank June 30, 2025 11:52
It's required that a response defines a name.
It's required that a response defines a name, i.e. implementations must verify that a consistent name is provided when
constructing a `HealthCheckResponse` instance, and fail accordingly if it is not.
Specific tests to verify this behavior are executed when running the TCKs.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I'm reading this @fabiobrz, don't you think it would be better to fail the deployment when such scenario is detected? So rather than 503, test here for DeploymentException. Also please point me to where you have an implementation that passes these new tests ;)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @xstefank. I am not sure about requiring DeploymentException to be thrown.

That would be a major change in the spec, for instance the SmallRye implementation is doing something different now, by throwing an IllegalArgumentException here: https://github.com/smallrye/smallrye-health/blob/main/implementation/src/main/java/io/smallrye/health/ResponseBuilder.java#L59

Failing to deploy would be something that the implementation might not know about (e.g.: when delegated to a component, like in the SMallRye case) and rather it should happen at the application server level (integration).

Or am I missing something?

Regarding your question about having an implementation that passes these new tests, I added the link in my last comment above, but anyway here it is: https://github.com/fabiobrz/wildfly/actions/runs/15956712879/job/45003958341 - but maybe too here I am not getting what you're asking for?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I'm reading this @fabiobrz, don't you think it would be better to fail the deployment when such scenario is detected? So rather than 503, test here for DeploymentException. Also please point me to where you have an implementation that passes these new tests ;)

Additionally, the new tests are checking something which happens when hitting the health endpoints, rather than when deploying.
And they only verify that a consistent name is provided when building responses via the static methods, rather than checking annotated health checks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, I forgot we don't have such test cases here as of now, but you can see an example here - https://github.com/microprofile/microprofile-lra/blob/main/tck/src/main/java/org/eclipse/microprofile/lra/tck/TckInvalidSignaturesTests.java.

It doesn't make sense to wait for the first health call when we can detect something right away.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HealthCheckResponse should enforce that the name cannot be null

3 participants