I have a RestController in which the request is sent by the post method.
#RequestMapping(value = "/params", method = RequestMethod.POST)
public OneObject getParams(#RequestBody NeededObject neededObject) {
// logics
}
After the server processes this request.
Comes the answer to callback endpoint.
#RequestMapping(value = "/callback", method = RequestMethod.POST)
public DifferentObject callback(#RequestBody OtherObject otherObject) {
// processing the response otherObject and if the success
// needs to redirect the request to another endpoint
// with the parameters of the first query,
// transfer to #RequestBody NeededObject neededObject
}
How can I implement this?
The first two endpoints are on the same controller, and I need to redirect it to another controller (Controller below).
#RequestMapping(value = "/need", method = RequestMethod.POST)
public OneDto create(#RequestBody NeededObject neededObject) {
// logics
}
I'm trying something (the code below), but I do not know if it's a good way.
And I do not know where to get the response to inserting it when include.
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/need");
requestDispatcher.include(request, response);
Thank you for your help.
Related
This is an anchor tag in jsp page calling a get url, from this url I am forwarding to a post request
Call1
call1url hit a get request in controller
#RequestMapping(value = "/call1url", method = RequestMethod.GET)
public String make(HttpServletRequest request) {
return "forward:/manctril";
}
to forward to a post request in controller
#RequestMapping(value = "/main", method = RequestMethod.POST)
public String make2(HttpServletRequest request) {
return "forward:/dash";
}
trying to perform the above returns an error similar to
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'GET' not supported
Is my attempt possible or while is it failing
I don't think GET to POST call can be done from the server by using redirect or forward, You need to redesign your Solution. You can try achieving it using below way:
a. You anchor Tag do a POST call to the controller using JS or AJAX, and then from one POST to another POST can be done, like below by setting a request attribute
request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.TEMPORARY_REDIRECT);
#RequestMapping(value = "/call1url", method = RequestMethod.POST)
public String make(HttpServletRequest request) {
request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.TEMPORARY_REDIRECT);
return "forward:/main";
}
#RequestMapping(value = "/main", method = RequestMethod.POST)
public String make2(HttpServletRequest request) {
return "dash";
}
b. Your Anchor Tag should go to a GET call, which should render a jsp/html page and then autosubmit the jsp as POST on the page/body load like below,
<body onload="document.forms['redirectToURLForm'].submit()">
<form:form method="POST" id="redirectToURLForm"
name="redirectToURLForm" action="main">
</form:form>
</body>
This will call the POST /main method.
I'm building a REST API using Java and Spring and I need to handle a POST request in my controller, but I need to extract the body from that request which is a JSON and also the "origin" of that request,
#RequestMapping(value = "/create", method = RequestMethod.POST)
public XXX createMyObject(#RequestBody String data, YYY){
MyObject mo = new MyObject();
mo.setData = data;
mo.setOrigin = yyy;
myRepository.save(mo);
return XXX;
}
I have a few questions: First is how can I obtain the origin of that request( which I guess is an url that travels in the header?), is there a similar annotation as the #RequestBody for that?.
My second question is what is usually the proper object to return in these kind of post methods as a response.
To answer your questions:
If you include HttpServletRequest in your method parameters you will be able to get the origin information from there. eg.
public XXX createMyObject(#Requestbody String data, HttpServletRequest request) {
String origin = request.getHeader(HttpHeaders.ORIGIN);
//rest of code...
}
For rest responses you will need to return a representation of the object (json) or the HttpStatus to notify the clients whether the call wass successful or not. eg
Return ResponseEntity<>(HttpStatus.ok);
You should be able to get headers and uris from HttpServletRequest object
public XXX createMyObject(#RequestBody String data, HttpServletRequest request)
As for response I'd say return String which would be a view name to which you can pass some attributes saying that operation was successful or not, or ModelAndView.
#Autowired
private HttpServletRequest servletRequest;
You can declare request object and then access in method to get Uri
Try this:
#RequestMapping(value = "/create", method = RequestMethod.POST)
public XXX createMyObject(HttpServletRequest request, #RequestBody String body) {
String origin = URI.create(request.getRequestURL().toString()).getHost();
System.out.println("Body: " + body + " Origin:" + origin);
return XXX;
}
I'm a little new in Java Spring. What I want to do is as follows:
Some 3rd party is asking a "return URL" from me and I set it as follows:
https://localhost:9002/my-account/order-history
Then they send me a POST request and I'm supposed to handle it within my controller. The request has both url parameters and a form data. The request is
Request URL:https://localhost:9002/my-account/order-history?responseCode=0000&token=E0ECFC1214B19E5D11B9B587920FC5F164C5CB17E7DC67F083E0EC6676F79467DFBDF4B6CCF3C39BF47F0232D1AA42F1FA112F29B0157DDF98EE3997F781CCB1FEB070A44E530691BA36674BEA4CF56A4A43F2B9746D9C3591CF288D745A6694
Request Method:POST
Status Code:403 Bad or missing CSRF token
Remote Address:127.0.0.1:9002
Referrer Policy:no-referrer-when-downgrade
A part of the form data is:
I added the whole form data and other request info as attachment.
The controller I'm desperately trying to use is as follows:
#Controller
#RequestMapping(value = "/my-account")
public class MaviAccountPageController extends MaviAbstractController
{
#RequestMapping(value = "/order-history", method = RequestMethod.POST)
public ModelAndView process(#RequestBody final String req)
{
//consumes = "text/plain"
System.out.println(req);
System.out.println(req);
return new ModelAndView("deneme");
}
....
}
And I keep getting 403 - Bad or missing CSRF token error.
How should I implement my controller? I have checked below links and they did not work out unfortunately:
How to retrieve FORM/POST Parameters in Spring Controller?
How to explicitly obtain post data in Spring MVC?
I tried, but failed to regenerate issue on postman.
Can anyone, please, advise me about how to move on?
you can annotate your method with #CrossOrigin
#CrossOrigin
#RequestMapping(value = "/order-history", method = RequestMethod.POST)
public ModelAndView process(#RequestBody final String req)
{
//consumes = "text/plain"
System.out.println(req);
System.out.println(req);
return new ModelAndView("deneme");
}
https://spring.io/guides/gs/rest-service-cors/
My Java spring REST API controller looks like this:
public void signup(#RequestBody RequestBody requestBody) throws IOException, ServletException {
I get this exception:
Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Stream closed; nested exception is java.io.IOException: Stream closed
This happens because I want to cast the request body to RequestBody class (which opens the request input stream and finishes it), and also forward/redirect it to another endpoint.
The actual controller is:
#RequestMapping(value = "/signup", method = RequestMethod.POST)
public void signup(#RequestBody CustomUserDetails user, HttpServletRequest request, HttpServletResponse response) {
String userName = user.getUsername();
logger.debug("User signup attempt with username: " + userName);
try{
if(customUserDetailsService.exists(userName))
{
logger.debug("Duplicate username " + userName);
userName + " already exists");
String newUrl = "login";
RequestDispatcher view = request.getRequestDispatcher(newUrl);
view.forward(request, response);
} else {
customUserDetailsService.save(user);
authenticateUserAndSetSession(user, response);
}
} catch(Exception ex) {
}
}
How should I handle this ?
You can forward to login page in a ExceptionHandler,like this:
#RequestMapping(value = "/signup", method = RequestMethod.POST)
public void signup(#RequestBody CustomUserDetails user, HttpServletResponse response) {
String userName = user.getUsername();
logger.debug("User signup attempt with username: " + userName);
//try{
if (customUserDetailsService.exists(userName)) {
logger.debug("Duplicate username " + userName);
throw new SignupException(userName + " already exists");
} else {
customUserDetailsService.save(user);
authenticateUserAndSetSession(user, response);
}
/*} catch(Exception ex) {
}*/
}
define a ExceptionHandler in the same Controller:
#ExceptionHandler(SignupException.class)
public String duplicateName() {
return "login";
}
and the SignupException could be like this:
public class SignupException extends RuntimeException {
public SignupException(String message) {
super(message);
}
public SignupException() {
}
}
The request body object is a stream which can be read only once. So forwarding it is not very trivial. One way around this is to create a filter which reads the input steam and replace the input stream to something which can be read multiple times. Example can be found at another answer:
How can I read request body multiple times in Spring 'HandlerMethodArgumentResolver'?
As for your method, there is also another problem:
public void signup(#RequestBody RequestBody requestBody)
As far as I know, RequestBody is an annotation and you can't map it like that. But to get the raw data, you can map it as String.
public void signup(#RequestBody String requestBody)
And then you can just manually make an REST call to the api you want to forward it to using the String request body. Just make sure you set the content-type as the original one, which I assume in this case would be JSON.
Root of your problem is using #RequestBody RequestBody requestBody together with HttpServletRequest request.
Opening input stream twice on the same request is not allowed. In your case a system should open a input stream to extract request body and then propagate in forward to reuse.
To handle it you should avoid multiple usage of the same request stream. Possible solutions are:
Wrap request
Copy request body
Use spring native forward
I think you are trying to forward to a url with the RequestBody, please have a check
Spring 3.2 forward request with new object for the answers.
Create the object and add it to the request as an attribute in the first controller,
request.setAttribute("user",user),
return "forward:/login";
Try putting in request mapping consumes= {" application/json"}, produces={"application/json"}
RequestBody is an annotation to process your request object as expected class deserialization. They help you avoid boilerplate code by extracting the logic of messageconversion and making it an aspect.
You can not get RequestBody directly as an object in any controller. It was not designed to use this way.
Though it is not possible to get RequestBody in a RestController so you can't judge whether it is good or bad practice.
If you have to use new controller/endpoint to process.Then i think the better approach is to get the CustomUserDetails as #RequestBody in the controller then process it. Then call nested method or service to further process instead of thinking forwarding to another controller. Then return response from the controller.
This is my first webservice and I am still understanding POST's GET's etc. I have been working on a Spring REST service. What I am confused about is how do I deal with a payload sent by another application?
Basically I have one app sending a json payload to my Spring REST API and I want to be able to grab the values of each key and store them in an object
Here is basically my code so far:
#RestController
public class Controller {
Payload payload;
Item item;
// gets the payload
#RequestMapping(value = "/buildevents/get-job", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseEntity <Payload> get() {
payload = new Payload();
payload.setJobName("Testing");
payload.setProjectName("Testing2");
payload.setUserName("Me");
payload.setPassWord("pass");
return new ResponseEntity<Payload>(payload, HttpStatus.OK);
}
#RequestMapping(value = "buildevents/create-item", method = RequestMethod.POST, headers = "Accept=application/json")
public ResponseEntity <Item> createItem(#RequestBody Item item) {
item.setProject(" ");
item.setItemName(payload.getJobName());
item.setUserName(" ");
item.setPassWord(" ");
return new ResponseEntity<Item>(item, HttpStatus.OK);
}
}
I want to do GET'S and POST'S from this code. The info I need to do so will come from a json payload POST to this service though, so I need to store the info from it in my object's setters. I don't know if I'm going about this wrong, but I'm lost.