Quarkus How to get all url query param? - rest

I would like to get all query params from an URL but I can't use #QueryParam without specifying a name, since names of paramters are dynamic, I can have some params that start with same name : param_toto, param_tata, param_titi, etc.
#QueryParam("") Map<String, String> queryParams
I get this error : RESTEASY003875: Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam("")
Please not that I don't want to use : HttpServletRequest since is not support by Quarkus, and I need to add a dependecy, of corse vertx has it implementation.

You can use #Context UriInfo uriInfo and call uriInfo.getQueryParameters()

Related

Renaming an XML/SOAP tag using Apache CXF

I've got a SOAP web-service server using Apache CXF as implementation. Due to some external technical constraint I'd like to be able to rename some XML tags naming an operation parameter (which are deprecated) in the inbound SOAP request. I was reading about using Interceptors for this, but the documentation on how to setup/configure them is not very clear.
My code to publish an endpoint is the following:
Endpoint endpoint = Endpoint.create(
"http://schemas.xmlsoap.org/soap/", new MyServer());
endpoint.publish("ws/endpoint");
Ideally I'd like to add a filter only to a given endpoint (I have several of them).
Apache's documentations about interceptors are quite clear (IMO), anyway, there is a helloworld project (based on spring boot, cxf and maven) in my github profile which you can take a look for setting up interceptors (in fact it's a baisc autentication interceptor).
For setting up an interceptor (e.g InInterceptor), your class should extend AbstractPhaseInterceptor<Message> and override handleMessage(Message message) method, then in the constructor you should declare the phase in which the interceptor is going to be applied. Finally you have to instantiate it and apply in on an Endpoint.
As you said:
rename some XML tags naming an operation parameter (which are
deprecated) in the inbound SOAP request
I think the name of the operation parameter (in WSDL file) is something different from the argument of your web method. Suppose that there is method in your endpoint named addPerson:
#WebMethod
String addPerson(Person person) {
/*method logic*/
}
and Person class:
class Person {
private String firstName;
private String lastName;
private Date birthDate;
//getters and setters
}
in order to map lastName property to a different name, you have to annotate it with
#XmlElement(name = "sureName")
private String lastName;
after applying this anotation, sureName (in wsdl file) is going to be mapped to lastName.
In addition, there is #WebParam annotation which can be used for changing the name of web method arguments:
#WebMethod
String sayHello( #WebParam(name = "sureName") String lastName);
Hope it helps.

Passing name-value pair from a map as query parameters in JAX-RS client

I am trying to access one existing REST service from my client side using JAX-RS client as below-
public interface ServerApi {
#POST
#Path("/server/{type}/add")
void addServer(#PathParam("type") String type);
}
Here I want to pass a map as method parameter and JAX-RS client will convert that to query parameters.
For example, if I pass a map ([name=test, vendor=top1]) as parameter (i,e, serverApi.addServer("linux", map);), JAX-RS client will transform it to /server/linux/add?name=test&vendor=top1
I tried to write the client interface method as below -
public interface ServerApi {
#POST
#Path("/server/{type}/add")
void addServer(#PathParam("type") String type, #PathParam("map") Map<String, String> aMap);
}
But it will not work as client will assign the entire map to map key and pass that query parameter and I am not expecting that.
Can anyone help me to achieve this using JAX-RS client

How to access suffixes using HTL/Sightly?

TLDR: Create a new AEM page called "mypage.html". Supply suffixes in the URL. Pass this suffixes to an Sling servlet. The suffixes act as URL parameters.
sample desired URL: http://localhost:4502/mypage.html/john/smith
So I created a servlet (used this guide: http://www.aemcq5tutorials.com/tutorials/sling-servlet-in-aem/) that can read a suffix.
#SuppressWarnings("serial")
#SlingServlet(paths="geometrixx/components/hompepage", selectors="name", extensions="html",methods="GET", metatype=true)
public class StaffProfileServlet extends SlingAllMethodsServlet {
private static final Logger log = LoggerFactory.getLogger(CourseBookmarkServlet.class);
#Override
protected void doGet(final SlingHttpServletRequest request,
final SlingHttpServletResponse response) throws ServletException, IOException {
RequestPathInfo rpi = request.getRequestPathInfo();
String[] suffixes = rpi.getSuffix().split("/");
and it working fine if I access it via http://localhost:4502/content/geometrixx/en.name.html/first/last
What I want to do next is create a new page called "mypage.html" and supply first and last as suffixes.
mypage will display information relevant to the person in a properly formatted page. With code above, all I get is JSON response.
Some assumptions/changes which I think is needed to achieve my goal:
I will be using paths and using request parameters (i.e. using request.getParameter("myparameter") on servlet code
I will be using AJAX to access the servlet
If my assumptions are correct, how do I access suffixes from HTL/Sightly? I understand I can get the URI via ${request.requestURI} or even Javascript. And using this value, I can then use this in my AJAX call.
But is this the AEM/Sling way of doing it? Or perhaps there is a better way to do what I want?
Thanks a lot!
You can use RequestPathInfo interface from HTL to access suffix's. ${request.requestPathInfo.suffix}
Global objects accessible through HTL -> here.
Methods accessible through request object -> here.

How to set custom object in body of message in cxf?

I have a REST webservice with method custom (GET).
#GET
#Path("/custom")
public UIResponse custom(final UIParameters uiParameters){...}
As you can see this method has one argument. This is my custom object.
Object UIParameters is built from argument given as query string.
eg. http://example.com/custom?objectType=article
UIParameters object will contain one field:
UIParameters {
String objectType = "article";
}
I have tried to use InInterceptor to get this parameter from URL, build UIParameter object and set Content of message. Unfortunatelly it doesn't work.
After that I've provide MessageBodyReader for UIParameters but it still doesn't work.
What should I do to achive this goal?
Thanks
Update:
In InInterceptor I've copied query string to http headers. Now part of URL where user place parameters is accessible in my MessageBodyReader. Here I can build my object UIParameters.
Everything works fine but I don't think that this solution is the best.
Does somebody know better solution?
AnnotationQueryParam("") allows to get all the query parameters injected.
You do not need an interceptor and it is not the recommended way. See CXF documentation http://cxf.apache.org/docs/jax-rs-basics.html#JAX-RSBasics-Parameterbeans
#GET
#Path("/custom")
public UIResponse custom(#QueryParam("") UIParameters uiParameters)
class UIParameters {
String objectType;
}
If you want to build the bean yourself using the query parameters use #Context UriInfo annotation
#GET
#Path("/custom")
public UIResponse custom( #Context UriInfo uriInfo){
MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
new UIParameters().Builder()
.objectType(params.getFirst("type"))
.build();
}

How to pass any number of headers to Feign client without knowing all the names?

I've a use case where I need to pass all headers that start with a certain prefix to the feign client. I don't know the number or exact names of these headers. There doesn't seem to be a way to to do this easily as the Feign client expects all headers to be specified using #RequestHeader("name"). It doesn't seem to support something like #RequestHeader HttpHeaders, which would be very useful.
Any suggestions?
As of this writing, Feign doesn't support dynamic headers or query parameters using a Map. The Spring Cloud Feign client relies on the Spring annotations instead of Feign annotations, and the implementations of AnnotatedParameterProcessor have a bug such that they don't do what the documentation states they should be doing.
RequestHeader doc:
If the method parameter is Map, MultiValueMap, or HttpHeaders then the
map is populated with all header names and values.
RequestParam doc:
If the method parameter is Map or MultiValueMap and a parameter name
is not specified, then the map parameter is populated with all request
parameter names and values.
I submitted a pull request that will fix this. Until then, I'm using an extension of SpringMvcContract that uses my own AnnotatedParameterProcessor implementations. I set the custom SpringMvcContract using a Feign.Builder as follows:
#Autowired
FormattingConversionService feignConversionService;
#Bean
#Scope(SCOPE_PROTOTYPE)
public Feign.Builder feignBuilder() {
return HystrixFeign.builder()
.contract(feignContract());
}
#Bean
public Contract feignContract() {
return new EnhancedSpringMvcContract(feignConversionService);
}
From the documentation, you should be able to specify a header map for dynamic headers.
In cases where both the header field keys and values are dynamic and the range of possible keys cannot be known ahead of time and may vary between different method calls in the same api/client (e.g. custom metadata header fields such as "x-amz-meta-" or "x-goog-meta-"), a Map parameter can be annotated with HeaderMap to construct a query that uses the contents of the map as its header parameters.
#RequestLine("POST /")
void post(#HeaderMap Map<String, Object> headerMap);