Any simple way to test a #RequestBody method? - java

If I have a #Controller method whose parameter is a #RequestBody param, I usually have to write some jQuery script or something similar to perform an AJAX request with JSON object in order to call that method. If I tried calling that method via a web browser directly, it returns with a Error 415 Unsupported Media Type.
Is there any alternative to just quickly call such method using browser without having to write some jQuery code? Like perhaps a way to write the JSON object in the URL/address bar?
code:
#RequestMapping("testCall")
#ResponseBody
public List<TestObject> getTestCall (#RequestBody TestParams testParams) {
return stuff;
}
public class TestParams {
private Integer testNumber;
//getter/setter for testNumber
}
I thought maybe I could just do:
http://localhost/testCall?testNumber=1
maybe Spring would auto populate a new TestParams instance with that property set to 1 but that didnt work...
maybe I need to do something extra for that?

The whole point of a #RequestBody annotated parameters is for the Spring MVC stack to use the HTTP request body to produce an argument that will be bound to the parameter. As such, you need to provide a request body. Sending a request body is very atypical for a GET request. As such, browsers don't typically support it, at least not when simply entering an address in the address bar and submitting the request.
You'll need to use a different HTTP client, like jQuery. I typically have a small Java project in Eclipse that's setup with an Apache HTTP components client which can send HTTP requests to whatever server. It takes a few seconds/minutes to setup the correct request body and run.

I have spent the last year building a REST API, and by far the best way to exercise that API manually is using the Chrome Extension, Postman. I cannot recommend this tool enough.
https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en
To test your simple example you'll need to invoke a POST (I assume that as you have a request body, but your controller method doesn't define a HTTP Verb) using POSTMAN to your Url (like the following example):
POST /contextRoot/testCall
{
"testNumber": 1
}
If you want to test your API automatically (which I recommend), you can use the excellent Spring Mvc Test project. This allows your to call your API via a rest-like DSL and assert that the response is in the shape you want. More details can be found here:
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html#spring-mvc-test-framework

you can add request params to the getTestCall method:
#RequestParam(value = "testNumber", required = false, defaultValue = "") String testNumber

There is a chrome app called Advanced REST client. You can pass the data in form of json to your controller using this chrome app. For eg. json data is
id:1,
name:"xyz"
whereas the controller can have #RequestBody Person form.
The Person class would be a POJO having id and name as instance variables. The Spring would automatically map the json data to the form.
I think this is the easiest and simplest way of checking your spring controller.
Check the extension Advanced REST client here

From what I know You can send JSON object to the webbrowser and it will be displayed without further need of AJAX.
useful tutorial:
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/

Related

How to have different JSON responses registered for a GET call

GET http://localhost/foo/api/v1/bars/:id
How to have different JSON responses registered for a GET call. We would like the GET call to return a separate response based on whether a CLI is invoking or the user interface is calling the API by passing a query parameter. But how do we register different serializers dynamically on the response.
You can use a User-Agent request header to identify the application doing the request. There are good tutorials to check how to access the headers in Spring, like this Baeldung one.

When to use different request methods in spring

I've been tasked with creating a simple REST API, where a single double is provided, and another one is derived from it according to some rules.
When creating a controller, I made the method for parsing said base double in two ways.
#GetMapping("calculate/{income:.+}")
public ResponseEntity<?> calculateEAT(#PathVariable double income){
return ResponseEntity.ok(TaxDAO.addResult(income));
}
#PostMapping("calculate/{income:.+}")
public ResponseEntity<?> calculateEAT(#PathVariable double income){
return ResponseEntity.ok(TaxDAO.addResult(income));
}
The only difference is the type of mapping used. The only difference I noticed was that I could type income in the browser address bar with GET mapping - and it worked. With post mapping, I could only get results using Postman.
I'm assuming it's possible to write an entire controller using GET mapping. I don't really feel like it's a good practice though. Are there any rules for using Request Methods in controllers?
GET and POST requests are different HTTP methods. The browser will do a GET request when you type something in the browser address bar, that is why you can only make it work in Postman (where you can select which HTTP method to use).
You should use GET when you want to retrieve something from the REST API. You should use POST when you want to submit something to the REST API, usually creating a resource or triggering some kind of process. You can read more about each HTTP method in the following online resources:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
https://www.restapitutorial.com/lessons/httpmethods.html

Which RequestBody type should be used if using the same payload to make another request?

Background
We are consuming the API from a 3rd-party vendor
Problem Statement:
I am building a wrapper API around another API. The same exact JSON payload that I will be receiving from the client to the wrapper API will also be used to make an HTTP request to the original API.
Currently I'm converting JSON which deserializes to a String. Is this the right approach if the payload is just passing through the wrapper API to the original API? In other words, is the #RequestBody type String okay for my use case or do I still need to deserialize to a Java Object?
Use Case for wrapper
If multiple teams consumed the API from the 3rd-party vendor, all teams would have to make changes if we were to switch vendors. If we create a wrapper, only one team would have to make the changes. There is no processing in this wrapper.
Controller Code:
#RestController
#RequestMapping(value = FolderController.PATH, produces = MediaType.APPLICATION_JSON_VALUE)
public class PersonController(){
static final String PATH = "/person";
private final PersonService personService;
#Autowired
public PersonController(PersonService personService){
this.personService = personService
}
#PostMapping
#ResponseBody
public String createPerson(#RequestBody String requestBody){
return personService.createPerson(requestBody);
}
Whether you need to deserialize depends on what processing is necessary for your wrapper. If you just want to pass the request further without changing it, this should work.
However, if you just need to proxy the request, consider using Smiley's HTTP Proxy Servlet for this task.
Or if you are wrapping the API to implement security around it, then consider using Spring cloud gateway
It is always better to follow coding practices and convert the request body to a java POJO class instead of a string. Converting to POJO has several advantages :
You could provide additional validations for the request body.
Incase the request body changes or if there are any issues it could be identified easily.
Provides better control over the request structure.In future , if the API that you are consuming changes the request body structure, you could change it from your API instead of adapting it at every API that consumes your API.

Jersey web service proxy

I am trying to implement a web service that proxies another service that I want to hide from external users of the API. Basically I want to play the middle man to have ability to add functionality to the hidden api which is solr.
I have to following code:
#POST
#Path("/update/{collection}")
public Response update(#PathParam("collection") String collection,
#Context Request request) {
//extract URL params
//update URL to target internal web service
//put body from incoming request to outgoing request
//send request and relay response back to original requestor
}
I know that I need to rewrite the URL to point to the internally available service adding the parameters coming from either the URL or the body.
This is where I am confused how can I access the original request body and pass it to the internal web service without having to unmarshall the content? Request object does not seem to give me the methods to performs those actions.
I am looking for Objects I should be using with potential methods that would help me. I would also like to get some documentation if someone knows any I have not really found anything targeting similar or portable behaviour.
Per section 4.2.4 of the JSR-311 spec, all JAX-RS implementations must provide access to the request body as byte[], String, or InputStream.
You can use UriInfo to get information on the query parameters. It would look something like this:
#POST
#Path("/update/{collection}")
public Response update(#PathParam("collection") String collection, #Context UriInfo info, InputStream inputStream)
{
String fullPath = info.getAbsolutePath().toASCIIString();
System.out.println("full request path: " + fullPath);
// query params are also available from a map. query params can be repeated,
// so the Map values are actually Lists. getFirst is a convenience method
// to get the value of the first occurrence of a given query param
String foo = info.getQueryParameters().getFirst("bar");
// do the rewrite...
String newURL = SomeOtherClass.rewrite(fullPath);
// the InputStream will have the body of the request. use your favorite
// HTTP client to make the request to Solr.
String solrResponse = SomeHttpLibrary.post(newURL, inputStream);
// send the response back to the client
return Response.ok(solrResponse).build();
One other thought. It looks like you're simply rewriting the requests and passing through to Solr. There are a few others ways that you could do this.
If you happen to have a web server in front of your Java app server or Servlet container, you could potentially accomplish your task without writing any Java code. Unless the rewrite conditions were extremely complex, my personal preference would be to try doing this with Apache mod_proxy and mod_rewrite.
There are also libraries for Java available that will rewrite URLs after they hit the app server but before they reach your code. For instance, https://code.google.com/p/urlrewritefilter/. With something like that, you'd only need to write a very simple method that invoked Solr because the URL would be rewritten before it hits your REST resource. For the record, I haven't actually tried using that particular library with Jersey.
1/ for the question of the gateway taht will hide the database or index, I would rather use and endpoint that is configured with #Path({regex}) (instead of rebuilding a regexp analyser in your endpoint) .
Use this regex directly in the #path, this is a good practice.
Please take a look at another post that is close to this : #Path and regular expression (Jersey/REST)
for exemple you can have regexp like this one :
#Path("/user/{name : [a-zA-Z][a-zA-Z_0-9]}")
2/ Second point in order to process all the request from one endpoint, you will need to have a dynamic parameter. I would use a MultivaluedMap that gives you the possibility to add params to the request without modifying your endpoint :
#POST
#Path("/search")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces({"application/json"})
public Response search( MultivaluedMap<String, String> params ) {
// perform search operations
return search( params);
}
3/ My 3rd advice is Reuse : make economy and economy make fewer bugs.
it's such a pitty to rewrite a rest api in order to perform solr search. You can hide the params and the endpoint, but could be great to keep the solr uri Rest formatting of the params in order to reuse all the search logic of solr directly in your api. This will make you perform a great economy in code even if you hide your solr instance behind you REST GATEWAY SERVER.
in this case you can imagine :
1. receive a query in search gateway endpoint
2. Transform the query to add your params, controls...
3. execute the REST query on solr (behind your gateway).

Get http response as a String using spring

is their a neat way to pass a model to jsp, render the jsp and return the html as string using Spring. The html is then used in an e-mail that is fired off programmitcally, I do not want to use freemarker, but maybe I should ?
The url being requested is part of the same app.
I want one of my service layer classes to be able to call a view and use the html as a String.
You can call requestDispatcher.include(request, response) method.
You will need to implement the request and response objects. The request object will provide all information to the dispatcher which page should be rendered, the response object you will pass to the call will then capture the result to a string (using e.g. a StringBuilder).
See e.g. this tutorial for more info.
I'm guessing a servlet filter will do the trick? Not really a Spring solution, but easy enough to do.
Also this answer seems relevant, although it is DWR that you may not necessarily want to use in this instance.
You can use Velocity to create an email template:
String text = VelocityEngineUtils.mergeTemplateIntoString(
velocityEngine, "emailTemplate.vm", model);
There is a complete chapter in the Spring reference docs of how Spring can be used to send emails of various types.

Categories