How to share data between two server using RequestBody and PostMapping? - java

I am trying to share data from one server(8081) to another(8082) in Spring Boot using ResponseEntity, but I am not able to built the body.
Here is the code which I have written,
Server 1-
#GetMapping("/redirect")
public ResponseEntity<Void> redirectPgServer(#RequestParam("txnId") String txnId,
#RequestParam("amount") String amount) {
// Redirect to server 2
ProductDetails ref=new ProductDetails();
ref.setTxnId("txnId");
ref.setAmount("amount);
HttpHeaders head = new HttpHeaders();
String url = "http://localhost:8082/redirect-server";
System.out.println(url);
head.setLocation(URI.create(url));
return new ResponseEntity<Void>(ref, head, HttpStatus.FOUND);
}
Server2-
#GetMapping(value = "/redirect-server")
public String validateData(#RequestBody ProductDetails ref)
{
//Server 2 receive data
System.out.println(ref.getAmount());
//Does not gives any output since it throws error Request Body Missing, also if I mention
post mapping above it throws error Request method 'GET' not supported]
return "index"; //Using Thymeleaf for displaying html page.
}
I am able to share the data using only header by manipulating the url and using PathVariable but I want to use Post Mapping as I want to hide the parameters in the Url which are visible to User at Browser. Also I have tried using RestTemplate which brings me back to Server 1 and it throws error- Spring rest template cannot convert from text/html utf8.

My suggestion is to annotate both methods with #PostMapping, in both remove just the #RequestBody Annotation. In the first server you should respond with a 307 HTTP Code (which is the temporary redirect) basically this tells to the browser, to retry the call to another endpoint(which is given into the Location header).
Something like this :
Server 1
#PostMapping(value = "/redirect", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity redirect(Product product) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setLocation(URI.create("http://localhost:8082/product"));
return new ResponseEntity(httpHeaders, HttpStatus.TEMPORARY_REDIRECT);
}
Server 2
#PostMapping(value = "/product", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public void redirect(Product prod) {
System.out.println(prod.getId());
//do your stuff
}
HTML Page
<html>
<body>
<form action="http://localhost:8081/redirect" method="POST">
<input name="id">
<input name="name">
<button type="submit">Send</button>
</form>
</body>
</html>
If you don't use a form, instead you use some kind of async call you MUST specify the url form encoding. Otherwise you will get a 405.
I've tried the code with postman and with a html page it does work correctly. (Tried with Firefox)
If something it's not clear don't esitate to ask.
I have found a similar question where i took inspiration from
A good way to redirect with a POST request?

Related

Post request has no params

some strange situation I have and need your help.
For clear understand communication flow (simple client-server communication):
3rd provider send POST callback (application/x-www-form-urlencoded) ---> to API. API take all parameters from POST request (here are issue - no params).
What I see in response payload on 3rd provider (what he did):
<form name="redirectToCaForm" action="http://someURL/api/consentFailed" method="POST" enctype="application/x-www-form-urlencoded">
</form>
<script>
document.redirectToCaForm.submit();
</script>
In API code looks like this to catch request and it params:
#PostMapping(path = "/api/consentFailed",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public ResponseEntity<?> postConsentFailedCallback(HttpServletRequest request,
#RequestParam final MultiValueMap<String, String> formParams) {
...
...
}
But not any formParams came. Request working only with written consume. Also I see and know what 3rd provider send, but why API doesn't catch params? Any suggestions will be appreciated.

Springboot submit not finding controller

When I click submit on my HTML form it is not hitting the /greeting endpoint
#org.springframework.stereotype.Controller
#EnableAutoConfiguration
public class Controller {
#Autowired
assessment.PdfGeneratorUtil pdfGenaratorUtil;
#GetMapping ("/")
String home() {
return "static/assessment.html";
}
#PostMapping("/greeting")
public String greetingSubmit() {
Map<String,String> data = new HashMap<String,String>();
data.put("name","James");
Thymeleaf config
#Configuration
public class TheymeLeafConfiguration {
#Bean
public ClassLoaderTemplateResolver emailTemplateResolver(){
ClassLoaderTemplateResolver emailTemplateResolver=new ClassLoaderTemplateResolver();
emailTemplateResolver.setPrefix("templates/");
emailTemplateResolver.setTemplateMode("HTML5");
emailTemplateResolver.setSuffix(".html");
emailTemplateResolver.setTemplateMode("XHTML");
emailTemplateResolver.setCharacterEncoding("UTF-8");
emailTemplateResolver.setOrder(1);
return emailTemplateResolver;
}
}
And a snippet of the html:
<form action="#" th:action="#{/greeting}" method="post">
Which when I submit the form doesn't hit the breakpoint on the POST controller (the same line as the Map) and I get a 405 in the browser:
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
The URL in the browser after submit is:
http://localhost:8080/assessment.html#
Project structure:
UPDATE
It is working with this code, in so far as it hits the Get controller method, and also the Post controller method on submission. I am not quite sure what changed.
Note I am not using #ModelAttribute at this point in time since I was testing that the controller methods are getting called at the correct times.
#GetMapping("/greeting")
String greetingForm() {
return "assessment";
}
#PostMapping("/greeting")
public String greetingSubmit() {
System.out.println(" HELLLOO HELLOOOO ");
Map<String,String> data = new HashMap<String,String>();
data.put("name","James");
try {
pdfGenaratorUtil.createPdf("greeting",data);
} catch (Exception e) {
e.printStackTrace();
}
return "finished";
}
With the minimal details that you have given in your code, I will try to answer your question.
The first problem that I see in your code is you are not passing any value to the method with postmapping, which I see at odd as post are used to create resource in rest.
So if you want to map the values received from input to some model data you need to do it using #ModelAttribute annotation.
#PostMapping("/greeting")
public String greetingSubmit(#ModelAttribute Greeting greeting) {
return "greeting";
}
See Spring boot form handling
Check whether your template webpages are found. I dont see any page mapping to show the result of this submission.
So you need to return some page name where your browser will forward the response of your form submission. So if you dont add that, spring find the method, executes the code, but dont know where to redirect. In this case as well it shows the 415 HttpStatus code.
So add something like below:
return "greeting";
So this above code will look for /templates/greeting.html as per your resolver configuration.
I assume you are also using spring security in your project (assumption from screenshot. [class SecurityConfig.])
If you use spring security, the CSRF filter is enabled by default in spring-boot. So either you need to disable it or add csrf param in your login form post request. (recommended). For the remaining forms, CSRF token will be automatically added to forms with hidden input.
To Disable CSRF:
In your spring securityConfig disable the csrf protection on HttpSecurity object something like below:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
.loginProcessingUrl("/authentication")
.usernameParameter("j_username")
.passwordParameter("j_password").permitAll()
.and()
.csrf().disable()
}
Or To add csrf in your login form as below:
input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />

pass parameter through <a href=""> and get it to spring mvc controller

I am trying to pass clusterId=1 as parameter from
<a href="http://192.168.11.134:8080/UniconnectConfigurationWeb/nodes?clusterId=1"> and get it into spring mvc controller through #PathParam("clusterId")Integer clusterId. But I'm getting 404 error.
Guide me how to pass parameter through anchor tag and how to hit controller and get the parameter value.
I am sharing my code below,
#RequestMapping(value = "/nodes?clusterId={clusterId}", method = RequestMethod.GET)
public ModelAndView nodes(#RequestParam("clusterId")Integer clusterId,HttpSession session, HttpServletRequest request) {
System.out.println(clusterId);
return dashboard;
}
}
<c:url var="myURL" value="http://192.168.11.134:8080/UniconnectConfigurationWeb/nodes">
<c:param name="clusterId" value="1"/>
</c:url>
Here you are using clusterId as Request Parameter , and passing from client side to server side. but in your server side code you are used ?clusterId={clusterId} in Request Mapping annotation and you are trying to receive that request parameter with #RequestParam Annotation. here #RequestParam is enough for receiving Request Parameter. so, no need to use this ?clusterId={clusterId}`, this is not correct way of writing server side URL.
it may helps you for better understanding #RequestParam vs #PathVariable

Pass form data from Spring Controller to an external endpoint

My issue:
Having a form in a simple HTML, with action="/myController".
I need to send the form data to my Controller and from there I need to make another POST to an external Controller.
<form method="post" action="/myController">
<textarea name="data"></textarea>
</form>
And my Spring Controller looks something like this:
#RequestMapping(method = RequestMethod.GET, value = "/myController")
#ResponseBody
public String myController(#RequestBody MultiValueMap<String, String[]> formData) {
RestTemplate rest = new RestTemplate();
ResponseEntity<String> response = rest.postForEntity("urlPath", formData, String.class);
String manipulatedResult = manipulateResult(response.getBody());
return manipulatedResult;
}
I need to pass form data, to my controller, it should send form data further to the "urlPath" and recieve a response. I need to manipulate that response and return a result.
My question is, how to send the form data further, without manipulating the request?
Thanks in advance.
Your Response doesn't need to be a String it can be a well formed java object. In this case i do not see any issue returning ResponseEntity object without converting this into String.
#ResponseBody will convert returned java object to JSON/Xml based response to outside world.
you can use ModelAndView class.
Refer the following link: http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/web/portlet/ModelAndView.html

How to return the Image as ResponseEntity<byte[]> and display same using Thyme leaf

I am using thyme leaf for one my project, I have problem in generating a QRCode and display the same in browser and I am using spring mvc framework.
I will send the product id to API layer, that has to create QR code for that id. That should not save in anywhere and return as response as byte[]
using thyme leaf framework have to display the image in browser
Please help on the same.
Regards
Mohan
Just send a HTTP request to your controller.
In your Thymeleaf template, set the source of your image to the url of your Spring MVC controller:
<img th:src="#{/controller/qr/${id}}" />
Provide a method in your controller that returns the image as ResponseEntity:
#RequestMapping (value="/qr/{id}", method = RequestMethod.GET)
public ResponseEntity<byte[]> getQRImage(#PathVariable final String id) {
byte[] bytes = ...; // Generate the image based on the id
// Set headers
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
return new ResponseEntity<byte[]> (bytes, headers, HttpStatus.CREATED);
}
More answers can be found in this question: Spring MVC: How to return image in #ResponseBody?

Categories

Resources