I use SoapUi to test my web service. I want to sent from SoapUi a list of parameter for a post method. Here is the code where I want to handle the list but is not working, I get a null pointer exception :
#POST
#Produces(MediaType.APPLICATION_JSON)
#Path("/subscribeList")
public Response subscribe( final MultivaluedMap<String, String> listoffields )
{
System.out.println( "The list has: " + listoffields.size() );
return Response.ok().build();
}
From soapui I send the parameters as queryparam.
Can anyone help me solve this problem and be able to send a list?
Inject UriInfo as the method parameter, and get the map with UriInfo.getQueryParameters().
public Response subscribe( #Context UriInfo uriInfo ) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
String name = queryParams.getFirst("name");
}
Or you can explicitly specify the each query param in the method signature
public Response subscribe( #QueryParam("name") String name,
#QueryParam("age") int age ) {
Related
I'm trying to use RestTemplate to call POST api like that :
RequestorParam test = new RequestorParam();
test.setScopeMcg("MCG");
test.setSituatedDealIds(situatedDealIds);
String url = "http://localhost:" + serverPort + "/retrieveAttributes";
ResponseEntity<SituatedDeals> response = restTemplate.postForEntity(url, test, SituatedDeals.class);
and the code of the controller is like ;
#PostMapping(value = "/retrieveAttributes", produces = "application/json")
#ResponseBody
#Duration
public SituatedDeals retrieveAttributes(
#RequestParam String scopeMcg,
#RequestBody SituatedDealIds situatedDealIds
) {
log.info("success")
}
i'm getting bad request, can someone help ?
According to your controller code, you are actually not returning any Response Entity of type SituatedDeals, just logging it as success. this might be the reason for the null object in response.
The scopeMcg is a RequestParameter so you should be passing it in a request param format i.e http://localhost:8080/retrieveAttributes?scopeMcg=MCG
Reference:Spring Request Param
Your test Object is the actual payload for your post request which should be of type SituatedDealIds object.
Reference: Rest-Template post for Entity
I am building a generic web service and need to grab all the query parameters into one string for later parsing. How can I do this?
You can access a single param via #QueryParam("name") or all of the params via the context:
#POST
public Response postSomething(#QueryParam("name") String name, #Context UriInfo uriInfo, String content) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
String nameParam = queryParams.getFirst("name");
}
The key is the #Context jax-rs annotation, which can be used to access:
UriInfo, Request, HttpHeaders,
SecurityContext, Providers
The unparsed query part of the request URI can be obtained from the UriInfo object:
#GET
public Representation get(#Context UriInfo uriInfo) {
String query = uriInfo.getRequestUri().getQuery();
...
}
Adding a bit more to the accepted answer. It is also possible to get all the query parameters in the following way without adding an additional parameter to the method which maybe useful when maintaining swagger documentation.
#Context
private UriInfo uriInfo;
#POST
public Response postSomething(#QueryParam("name") String name) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
String nameParam = queryParams.getFirst("name");
}
ref
I have a SpringBoot application which simply acts as a middleman. It receives an API request in JSON and forwards this to another server S by calling S's API with the exact same body.
I was exploring the solutions and came across a solution which involved the usage of RestTemplate and MultiValueMap. However, since the json body contains objects rather than simple String, I believe I have to create a DTO with corresponding POJO for the solution to work.
May I ask is the above the only solution, or there is a simple way to forward the request over and get back the response?
Even complex and nested JSON objects can be taken into a Map with key as String and value as Object.
I believe you should just use such a map as your request body and transfer the same to another api.
The middleman server can expose a endpoint that accepts a #RequestBody of Object and
HttpServletRequest then use RestTemplate to forward it to the remote server.
The middleman
#RestController
#RequestMapping("/middleman")
public class MiddleManRestController {
private RestTemplate restTemplate;
#PostConstruct
public void init() {
this.restTemplate = new RestTemplate();
this.restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(this.restTemplate.getRequestFactory()));
}
#RequestMapping(value = "/forward", method = RequestMethod.POST)
public ResponseEntity<Object> forward(#RequestBody Object object, HttpServletRequest request) throws RestClientException {
//setup the url and path
final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("Remote server URL").path("EnpointPath");
//add query params from previous request
addQueryParams(request, builder);
//specify the method
final RequestEntity.BodyBuilder requestBuilder = RequestEntity.method(HttpMethod.POST, builder.build().toUri());
//add headers from previous request
addHeaders(request, requestBuilder);
RequestEntity<Object> requestEntity = requestBuilder.body(object);
ParameterizedTypeReference<Object> returnType = new ParameterizedTypeReference<Object>() {};
//forward to the remote server
return this.restTemplate.exchange(requestEntity, returnType);
}
private void addHeaders(HttpServletRequest request, RequestEntity.BodyBuilder requestBuilder) {
Enumeration<String> headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
requestBuilder.header(headerName, headerValue);
}
}
private void addQueryParams(HttpServletRequest request, UriComponentsBuilder builder) {
final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
Map<String, String[]> parameterMap = request.getParameterMap();
if (parameterMap != null) {
parameterMap.forEach((key, value) -> queryParams.addAll(key, Arrays.asList(value)));
}
builder.queryParams(queryParams);
}
}
I'm trying to get the body of a POST request by using HttpServletRequest or UriInfo. Given a class like this one (reduced for this question):
#Path("/nodes")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({ MediaType.APPLICATION_JSON })
public class Nodes {
public NodeResource() {
//initial stuff goes here
}
/**
* gives an empty response. For testing only!
*/
#POST
#Consumes("application/json")
#Path("{id}/test-db-requests")
public Response giveNodes(#PathParam("id") final String id, #Context HttpServletRequest request, #Context UriInfo uriInfo){
//String readReq = request.getQueryString(); //would work for GET
MultivaluedMap<String,String> readParams = uriInfo.getQueryParameters();
LOG.debug("what is readParams?", readParams); //goes, but shows nothing
if (readParams != null) {
LOG.debug("null or not?"); //goes, too
for (Map.Entry<String,List<String>> entry: readParams.entrySet()) {
List<String> values = entry.getValue();
LOG.debug("params POST key: {}", entry.getKey()); // goes not
for (String val: values) {
LOG.debug("params POST values: {}", val);
}
LOG.debug("params POST next entry:::");
}
}
List<?> results = null; //currentDBRequest(id);
List<?> content = new ArrayList<>();
if (results != null) {
content = results;
}
return Response.ok(content).build();
}
}
Instead of using
MultivaluedMap<String,String> readParams = uriInfo.getQueryParameters();
//not possible at all - for GET only!? See first comment.
I also tried to use
Map<String,String[]> readParams = request.getParameterMap();
//what is about this one?
with different following code of course. But that did not work, either.
So when I fire a simple request like /nodes/546c9abc975a54c398167306/test-db-requests with the following body
{
"hi":"hello",
"green":"tree"
}
(using an JSON Array does not change anything)
and stuff in the HEADER (some informations):
Content-Type: application/json; charset=UTF-8
Accept: application/json, text/plain, */*
Connection: keep-alive
the result is disappointing, readParams is not null, but does not contain any data. Before I start to play with getReader I wanted to ask: what am I doing wrong? Is there a problem in my POST, in my Java code or in the used HttpServletRequest method(s)? Thanks!
Related questions (where I found some possible solutions), among others:
How can I grab all query parameters in Jersey JaxRS?
How to access parameters in a RESTful POST method
Alright, Jackson would actually do this for me. Just use the argument of the method, which you want to use. (See examples below.)
But you would probably not use a POST in combination with an id parameter. POST is usually used for saving fresh resources, which do not have an id (in the DB, a primary key). Moreover the path /api/{resource_name}/{id}/{some_view} would be useful for GET. Just api/{resource_name}/{id} for a GET (single entry) or a PUT (update an existing entry).
Assume you are in a resource for Pet.class. You want to catch the POSTs for this class in order to do something special with them, based on the view test-db-requests. Then do:
#POST
#Consumes("application/json")
#Path("{id}/test-db-requests")
public Response giveNodes(final String pet, #PathParam("id") final String id){
//do stuff for POST with a strigified JSON here
}
or
#POST
#Path("{id}/test-db-requests")
public Response giveNodes(final Pet pet, #PathParam("id") final String id){
//do stuff for POST with an instance of pet here (useful for non
//polymorphic resources
}
I am building a generic web service and need to grab all the query parameters into one string for later parsing. How can I do this?
You can access a single param via #QueryParam("name") or all of the params via the context:
#POST
public Response postSomething(#QueryParam("name") String name, #Context UriInfo uriInfo, String content) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
String nameParam = queryParams.getFirst("name");
}
The key is the #Context jax-rs annotation, which can be used to access:
UriInfo, Request, HttpHeaders,
SecurityContext, Providers
The unparsed query part of the request URI can be obtained from the UriInfo object:
#GET
public Representation get(#Context UriInfo uriInfo) {
String query = uriInfo.getRequestUri().getQuery();
...
}
Adding a bit more to the accepted answer. It is also possible to get all the query parameters in the following way without adding an additional parameter to the method which maybe useful when maintaining swagger documentation.
#Context
private UriInfo uriInfo;
#POST
public Response postSomething(#QueryParam("name") String name) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
String nameParam = queryParams.getFirst("name");
}
ref