1

How can I access URL query parameters from the http request in Lagom? I have a requirement where the set of query parameters are indefinite and infinite. I want to access the query parameter as a map. Is there any way to do that?

3 Answers3

1

There isn't currently a way to access the query parameters as a map, or to declare a service call that takes indefinite parameters, as of Lagom 1.3.

In situations where the request may be of arbitrary length or complexity, it is better to encode request data in the entity body and use a request message deserializer in Lagom to map that to an immutable data type.

Tim Moore
  • 5,931
  • 1
  • 19
  • 24
  • But, if I encode request data in entity body and deserialize it to a DTO, I won't be able to cater for HTTP GET requests as I have to provide a payload to the HTTP object. Is my understanding right? – Abhishek Mukhopadhyay Feb 28 '17 at 02:00
  • That's correct. You'll need to use a `POST` request. – Tim Moore Feb 28 '17 at 02:50
  • Actually, you can use a `GET` request with a payload in Lagom if you force the `Method` in a `restCall`. But using `GET` with a payload is a bad idea as discussed in http://stackoverflow.com/questions/978061/http-get-with-request-body . – ignasi35 Feb 28 '17 at 10:29
0

From the docs:

Query string parameters can also be extracted from the path, using a & separated list after a ? at the end of the path. For example, the following service call uses query string parameters to implement paging: ServiceCall> getItems(long orderId, int pageNo, int pageSize);

default Descriptor descriptor() {
    return named("orders").withCalls(
            pathCall("/order/:orderId/items?pageNo&pageSize", this::getItems)
    );
}

Check this link for more details.

Koustav Ray
  • 933
  • 10
  • 24
  • Such descriptors can be used when the service call has a finite set of query parameters predefined. Lagom internally binds the query paramters value to the name identifiers in the url pattern. What if the set of query parameters to the URL is infinite and indefinite? – Abhishek Mukhopadhyay Feb 28 '17 at 02:05
  • Well in Such cases there exists no Generic ways to achieve that as mentioned by Tim. However I find it slightly odd that you will be needing Queryparams that you will not have any pre-knowledge of. I mean How and more importantly why would that be required is slightly strange. But in case of your specific usecase I believe Post is the way to go.. – Koustav Ray Mar 04 '17 at 19:33
0

https://github.com/msdhillon8989/lagom-demo-request-header.git

you can use the HeaderServiceCall of lagom.

@Override
public ServiceCall<NotUsed, String> method1() {
    return readHeader(
        new Function<String, ServerServiceCall<NotUsed, String>>() {
            @Override
            public ServerServiceCall<NotUsed, String> apply(String param) throws Exception {
                return request -> {
                        return completedFuture(Utilities.ok(null, parseQueryString(param).toString()));
                };
            }
        });
}

Definition of readHeader function is as below

public <Request, Response> ServerServiceCall<Request, Response> readHeader(Function<String, ServerServiceCall<Request, Response>> serviceCall) {
    return HeaderServiceCall.composeAsync(new java.util.function.Function<RequestHeader, CompletionStage<? extends ServerServiceCall<Request, Response>>>() {
        @Override
        public CompletionStage<? extends ServerServiceCall<Request , Response>> apply(RequestHeader requestHeader) {
            CompletableFuture<String> uri =  CompletableFuture.supplyAsync(()->requestHeader.uri().getRawQuery().toString());
            return uri.thenApply(query->
            {
                try {
                    return serviceCall.apply(query);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new Forbidden("Bad request "+e.getMessage());
                }
            }
            );
        }
    });
}