Comments (11)
I hit something similar to this the other day and worked around it with:
var query = req.query();
if (!query.isEmpty() && query.get("period") instanceof String period) {
Having to check the isEmpty
is kind-of a pain. Tho the out-of-bounds you got seems worse.
from helidon.
@talios have you tried:
var period = req.query().first("period").asString().orElse("whatever);
//or
req
.query()
.first("period")
.asString()
.ifPresent(period->{....});
from helidon.
@hrstoyanov That works nicely - even better using .as(Period::parse)
to map to the desired type. Much cleaner - cheers!
from helidon.
Reason for this bug is that the implementation did not expect an empty list as a value in the map used to create it.
The place we introduced this (I think the only one) is in URI Query, where we handle the case of a parameter without a follow-up =
as a name without a value - so contains
returns true, but there is no value.
So we were missing a validation of the map for the assumption of the implementation, and a change once we decided to support it.
The only sloppiness I see here is the lack of test for a query parameter without a value...
from helidon.
@tomas-langer apologies, the code is actaully very nicely designed maybe needs unit test, I updated the initial report. Sorry!
from helidon.
Merged, thank you for reporting it
from helidon.
I have not looked at the fix details, but can you , please, confirm that this code:
ServerRequest req = ...;
var params = eq.content().as(Parameters.class);
will not fail with:
io.helidon.http.RequestException: No entity
at [email protected]/io.helidon.http.RequestException$Builder.build(RequestException.java:139)
at [email protected]/io.helidon.webserver.http.ErrorHandlers.unhandledError(ErrorHandlers.java:203)
at [email protected]/io.helidon.webserver.http.ErrorHandlers.lambda$handleError$1(ErrorHandlers.java:182)
but rather - return an empty Parameters object? That way developers need not do noise checks, as it is the case in 4.0.8:
var content = req.content();
if(content.hasEntity()) {
var params = content.as(Parameters.class)
}
from helidon.
I think this is another issue. I was working in the:
Caused by: java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
That was happening when you were expecting an optional.
But in the example you wrote, .as(Parameters.class);
does not return an optional. I think it is fine to throw an exception because otherwise we need to return null. We would need to change the API to return an Optional.
@tomas-langer is on vacations but he can review it when he comes back.
from helidon.
Thanks @jbescos , I see. My suggestion is to return Parameters object always, but perhaps with empty parameters, if possible.
Also, take a look at issue #8652:
The test case example shown uses exactly the kind of code from above that can fail:
req.content().as(Parameters.class);
from helidon.
I am running one test I have created:
// Client
@Test
public void testFormNoEntity() {
try (Http1ClientResponse res = client.post("/form/content").request()) {
Parameters received = res.as(Parameters.class);
assertThat(received.first(NO_VALUE).isEmpty(), is(true));
}
}
// Server
private void formContent(ServerRequest req, ServerResponse res) {
Parameters form = req.content().as(Parameters.class);
res.send(form);
}
And I am hitting the exception with the next stacktrace:
System Thread [[0x7ee4364d 0x4afac8ea] WebServer socket] (Suspended)
io.helidon.http.media.ReadableEntityBase$EmptyReadableEntity.as(java.lang.Class<T>) line: 255
io.helidon.webclient.tests.GreetService.formContent(io.helidon.webserver.http.ServerRequest, io.helidon.webserver.http.ServerResponse) line: 193
io.helidon.webclient.tests.GreetService$$Lambda.0x00007f02fc228250.handle(io.helidon.webserver.http.ServerRequest, io.helidon.webserver.http.ServerResponse) line: not available
io.helidon.webserver.http.HttpRoutingImpl$RoutingExecutor.doRoute(io.helidon.webserver.ConnectionContext, io.helidon.webserver.http.RoutingRequest, io.helidon.webserver.http.RoutingResponse) line: 165
io.helidon.webserver.http.HttpRoutingImpl$RoutingExecutor.call() line: 124
io.helidon.webserver.http.HttpRoutingImpl$RoutingExecutor.call() line: 102
io.helidon.webserver.http.ErrorHandlers.runWithErrorHandling(io.helidon.webserver.ConnectionContext, io.helidon.webserver.http.RoutingRequest, io.helidon.webserver.http.RoutingResponse, java.util.concurrent.Callable<java.lang.Void>) line: 75
io.helidon.webserver.http.Filters$FilterChainImpl.proceed() line: 121
io.helidon.webserver.security.SecurityContextFilter.filter(io.helidon.webserver.http.FilterChain, io.helidon.webserver.http.RoutingRequest, io.helidon.webserver.http.RoutingResponse) line: 88
io.helidon.webserver.http.Filters$FilterChainImpl.proceed() line: 119
io.helidon.webserver.observe.tracing.TracingObserver$TracingFilter$$Lambda.0x00007f02fc2c8f10.run() line: not available
io.helidon.common.context.Contexts.runInContext(io.helidon.common.context.Context, java.lang.Runnable) line: 117
io.helidon.webserver.observe.tracing.TracingObserver$TracingFilter.filter(io.helidon.webserver.http.FilterChain, io.helidon.webserver.http.RoutingRequest, io.helidon.webserver.http.RoutingResponse) line: 247
io.helidon.webserver.http.Filters$FilterChainImpl.proceed() line: 119
io.helidon.webserver.context.ContextRoutingFeature$$Lambda.0x00007f02fc2c1918.run() line: not available
io.helidon.common.context.Contexts.runInContext(io.helidon.common.context.Context, java.lang.Runnable) line: 117
io.helidon.webserver.context.ContextRoutingFeature.filter(io.helidon.webserver.http.FilterChain, io.helidon.webserver.http.RoutingRequest, io.helidon.webserver.http.RoutingResponse) line: 50
io.helidon.webserver.context.ContextRoutingFeature$$Lambda.0x00007f02fc222ee0.filter(io.helidon.webserver.http.FilterChain, io.helidon.webserver.http.RoutingRequest, io.helidon.webserver.http.RoutingResponse) line: not available
io.helidon.webserver.http.Filters$FilterChainImpl.proceed() line: 119
io.helidon.webserver.http.Filters.executeFilters(io.helidon.webserver.http.FilterChain) line: 87
io.helidon.webserver.http.Filters.lambda$filter$0(io.helidon.webserver.http.FilterChain) line: 83
io.helidon.webserver.http.Filters$$Lambda.0x00007f02fc2c14d8.call() line: not available
io.helidon.webserver.http.ErrorHandlers.runWithErrorHandling(io.helidon.webserver.ConnectionContext, io.helidon.webserver.http.RoutingRequest, io.helidon.webserver.http.RoutingResponse, java.util.concurrent.Callable<java.lang.Void>) line: 75
io.helidon.webserver.http.Filters.filter(io.helidon.webserver.ConnectionContext, io.helidon.webserver.http.RoutingRequest, io.helidon.webserver.http.RoutingResponse, java.util.concurrent.Callable<java.lang.Void>) line: 83
io.helidon.webserver.http.HttpRoutingImpl.route(io.helidon.webserver.ConnectionContext, io.helidon.webserver.http.RoutingRequest, io.helidon.webserver.http.RoutingResponse) line: 73
io.helidon.webserver.http1.Http1Connection.route(io.helidon.http.HttpPrologue, io.helidon.http.WritableHeaders<?>) line: 357
io.helidon.webserver.http1.Http1Connection.handle(java.util.concurrent.Semaphore) line: 194
io.helidon.webserver.ConnectionHandler.run() line: 165
io.helidon.webserver.ConnectionHandler(io.helidon.common.task.InterruptableTask<T>).call() line: 47
io.helidon.webserver.ThreadPerTaskExecutor$ThreadBoundFuture<T>.run() line: 239
java.lang.VirtualThread.runWith(java.lang.Object, java.lang.Runnable) line: 341
java.lang.VirtualThread.run(java.lang.Runnable) line: 311
java.lang.VirtualThread$VThreadContinuation$1.run() line: 192
java.lang.VirtualThread$VThreadContinuation(jdk.internal.vm.Continuation).enter0() line: 320
jdk.internal.vm.Continuation.enter(jdk.internal.vm.Continuation, boolean) line: 312
The exception is explicitly thrown in this line:
The question is whether we can return an empty value instead of failing. Lets wait for @tomas-langer to review it.
from helidon.
@tomas-langer ^^^
from helidon.
Related Issues (20)
- 4.x: tests/integration/dbclient/mongodb is not part of reactor
- Helidon 4.0.9 gets NPE on context aware wrapped async virtual thread use in JaegerDataPropagationProvider.java:41 HOT 2
- [4.x] Undesirable exception: io.helidon.http.RequestException: No entity
- Using Helidon default for pluggable in OCI SDK
- 4.x: OCI archetype server throws `UnsatisfiedResolutionException` HOT 4
- 3.x: `examples.mp.httpstatuscount.StatusTest` test hangs on Java 21
- Consider replacing usages of ConcurrentHashMap HOT 1
- 4.x: WebServer double compression (re-encoding)
- Revise Zipkin tracer provider implementation so it implements the Helidon neutral tracing API
- Zipkin (and OpenTracing) tracing providers do not provide context propagation
- `HelidonTest` docs do not describe interaction with MicroProfile Config profiles
- Profile does not apply in helidon mp configuration made by meta-config.yaml HOT 1
- Check delegate before Helidon wrapper in tracer `unwrap` method
- Add the ability to get the ip address of the client in websocket
- Fail HelidonTests by defaul when pinning jfr event is detected HOT 6
- Add mvn targets for GraalVM Enterprise PGO
- Helidon tracing custom spans HOT 3
- [4.x] Sample MP database app fails to compile w/JDK 22 (Native Image) HOT 1
- EclipseLink Sample fails to compile to Graal Native Image
- Health check timeout message should identify which health check timed out
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from helidon.