Generating WADL request parameters for #InjectParam - rest

I am using the #InjectParam to inject query parameters into a JAX-RS resource that contains #QueryParam annotated fields on a Jersey 1.12 implementation.
On the Resource:
#Path("query")
#GET
#Produces(MediaType.APPLICATION_XML)
public Query queryParam(#InjectParam Query query) {
return query;
}
And in the pojo that receives the injected parameters I have some JAXB and JAX-RS annotations.
#XmlRootElement
public class Query {
#QueryParam("value1")
String value1;
}
A simple test from a REST client:
http://localhost:8888/sandbox/query?value1=hello3
Produces the correct results:
<query>
<value1>hello3</value1>
</query>
That's great, but I also use the wadl-maven-plugin to generate a client which uses the WADL file to produce client code. The WADL file does not include the necessary request parameters that would be there if the #QueryParam annotation was included in the resource method parameters. Subsequently my client is produced to accept no parameters:
SandboxApi.sandbox().query().getAsQuery()
instead of accepting a populated generated client pojo.
Query queryClient = new Query();
queryClient.setValue1("hello3");
SandboxApi.sandbox().query().getAsQuery(queryClient);
Anyone know of a magic annotation I can put on the Jersey Resource that will produce a WADL with the right information so Wadl2Java could generate a client that will accept the POJO and subsequently send the appropriate fields as query parameters?

A response provided (via a private conversation) from some of the fine people working on Jersey:
#Path("query")
#GET
#Produces(MediaType.APPLICATION_XML)
public Query queryParam(#QueryParam("value1") String value1,
#InjectParam Query query) {
return query;
}
query param "value1" should appear in generated WADL.
In-built WADL generator does not contain support for these cases and I'm not sure whether it will be supported anytime soon.

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 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();
}

Jersey 2.x issue with MultivaluedMap

I am using Jersey 2.3.1 on Glassfish 4.
My resource method is similar to the following:
#POST
#Consumes("application/x-www-form-urlencoded")
#Path("/update")
public Response update(MultivaluedMap<String, String> formParams){
//business logic
//return appropriate Response object
}
I always get formParams.size() as zero. Why the submitted form parameters are not available in the MultivaluedMap object?
The following warning message in the server log:
WARNING: A servlet request to the URI http://localhost:8080/myApp/resource/update contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using #FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected.
(I tested before and after disabling all Servlet filters. I am not using any Jersey filters)
You get this message if request body with form data was already consumed by calling HttpServletResponse.getParameter(paramName). This can happen if any registered servlet filter called this method. Jersey ContainerRequestFilter cannot influence it. So I suggest to investigate the configuration of your deployment (web.xml). I have tested injecting Form entity with Jersey 2.5-SNAPSHOT and Glassfish 4 night build (glassfish-4.0.1-b04-12_04_2013) and it works.
If request body is already consumed you can still use form parameters but you cannot inject them as an entity (like in your code). If parameters are consumed, you can inject parameters using #FormParam JAX-RS annotation:
#POST
#Consumes("application/x-www-form-urlencoded")
public String postForm(#FormParam("paramKey") String paramValue) {
return paramValue;
}

How to sort dojox.grid.DataGrid with wink-based REST API?

I'm using the Dojo datagrid client side, it works well and according to documentation it generates the following GET request when clicking on the column header:
GET http://localhost:8080/books/rest/books?sort(+isbn)
Problem is that I can't interpret the query parameter "sort(+isbn)" on the server side using the Apache Wink framework, because there's no value set for it. E.g. I'd expect something like "sort=+isbn" instead.
Here's my server side code:
#Path("/books")
public class BookServiceImpl implements BookService {
...
#GET
#Produces(MediaType.APPLICATION_JSON)
public String getBook(#QueryParam("sort") String sortBy) {
System.out.println("Received Queryparam for sort is " + sortBy);
return "";
}
}
Since "sort(+isbn)" has no value assigned to it, it appears to be an invalid query parameter. Not sure why Dojo datagrid uses this convention.
Would appreciate help as to how to work around this on the Java side, ideally using Wink or another mechanism to process GET requests.
Try to use #Context UriInfo to get the full uri info, call to UriInfo.getQueryParameters to get all query params. I believe sort(+isbn) will be there.