Spring boot/Spring MVC - How to forward a response from another request - spring

I need a rest end point whose response is HTML. But instead of a view defined in my project, i would like to forward the HTML response from another request made inside that rest end point.
For example, my rest end point makes a http request to an internal service and returns the HTML returned from that service? Is it possible? Any thoughts?
Here is a code example
#RequestMapping("/test")
public String testMe(Model model, #RequestParam("param1") String param1, #RequestParam("param2") String param2)
{
//Make a Http call to an internal service and return the response from that call
return "<RESPONSE_FROM_THAT_CALL>";
}
I would like to return the HTML response from the internal service

You can use a RestTemplate to fetch the result from the other service and just return it as a String:
#Controller
public class MyController {
private RestTemplate restTemplate = new RestTemplate();
#ResponseBody
#RequestMapping("/test")
public String testMe(Model model, #RequestParam("param1") String param1, #RequestParam("param2") String param2) {
URI uri = UriComponentsBuilder.fromHttpUrl("http://www.example.com");
.queryParam("param1", param1)
.queryParam("param2", param2)
.build()
.toUri());
return restTemplate.getForObject(uri, String.class);
}
}
If you'll have more endpoints that you wanna proxy to another service, you should consider using e.g. Zuul as a micro proxy. See e.g. this blog post explaining how you can easily create such a proxy.

Related

RestTemplate exchange call return result in XML format

We have two Microservice Services1 and Service2.
In Service1 we have one PostMapping and return boolean value as below.
#PostMapping
public boolean reset(){
return true
}
When consume from Service2 through restTemplate exchange method it will return in XML format as below.
boolean val = restTemplate.exchange(url, Post method, http entity with header, Boolean.class);
Output
<boolean>true</boolean>
we expecting in JSON format in resttemplate call and if try through postman it will return in JSON.

Spring cloud stream messaging system(RabbitMQ) implementation using Rest Controller(Restful API)

From past few days i'm trying to implement the Spring cloud stream messaging system using RestController, but it is not happening through the current implementation.
For this sample code i'm going to add RestController
#EnableBinding(Source.class)
#EnableConfigurationProperties(TimeSourceOptionsMetadata.class)
public class TimeSource {
#Autowired
private TimeSourceOptionsMetadata options;
#InboundChannelAdapter(value = Source.OUTPUT)
public String timerMessageSource() {
return new SimpleDateFormat(this.options.getFormat()).format(new Date());
}
}
But the #InboundChannelAdapter cannot accept any parameters from RequestMapping Get Method URL.At the end what i need is to add message to the broker using Restful API Get method from api call. which is the best way to do it?, I couldn't figure out any best process from internet.
spring cloud team already provided a source application that listens for HTTP requests and emits the body as a message payload. If the Content-Type matches text/* or application/json, the payload will be a String, otherwise the payload will be a byte array.
github link
You can go with this or if you want to write it yourself, you can do it like below:
#RestController
#EnableBinding(Source.class)
public class RestSource {
#Autowired
private Source channels;
#RequestMapping(path = "/", method = POST, consumes = {"application/json" })
#ResponseStatus(HttpStatus.ACCEPTED)
public void handleRequest(#RequestBody String body, #RequestHeader(HttpHeaders.CONTENT_TYPE) Object contentType) {
sendMessage(body, contentType);
}
private void sendMessage(Object body, Object contentType) {
channels.output().send(MessageBuilder.createMessage(body,
new MessageHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE, contentType))));
}
}

Jersey get credentials from url

I have an url like this:
http://log:pass#localhost:8080/myendpoint
And Jersey endpoint:
#GET #Produces(MediaType.APPLICATION_JSON) #Path("/login")
#Consumes(MediaType.APPLICATION_JSON) public Response login(
#Context HttpHeaders headers, #QueryParam("callback") String callback)
{
}
And ideally I want to get 'log' and 'pass' in my endpoint method. How to do that in Jersey? I tried many endpint method signatures, filters, etc but it shows me
http://localhost instead of http://log:pass#localhost everywhere
How to achieve this?
Assuming that in your front end, you are sending your parameters as a json object using JSON.stringify() then back in your endpoint method. Add this as a second argument to that method signature JsonObject payload. Then you can access your query parameters within that method as follows
String log = payload.getString("log");
String pass = payload.getString("pass");
Revised Version
#Path("/login")
#GET
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response login(#Context UriInfo uriInfo, #Context HttpHeaders headers, #QueryParam("callback") String callback) {
URI requestUri = uriInfo.getRequestUri();
String authority = requestUri.getAuthority(); // authority contains what you need;
}

spring rest app, can't get data from PUT

I have two methods in controller, this is handler request from client. I can't get request body of PUT. For send request i use Advanced Rest Client in Chrome.
#RequestMapping(value = "/addPupil", method = RequestMethod.POST)
public void addPupil(Pupil pupil){
System.out.println(pupil.toString());
}
Result in Advanced Rest Client:
Status 200 OK Response does not contain any data.
stdout:
Pupil{address='is address', level='is level', group='is group', last='is last', name='is name'}
But problem with this method, i can't get pupil object!
#RequestMapping(value = "/changePupil/{id}", method = RequestMethod.PUT)
public void changePupil(#PathVariable("id") Long id, Pupil pupil){
System.out.println("id: "+id);
System.out.println(pupil.toString());
}
Result in Advanced Rest Client:
Status 200 OK Response does not contain any data.
stdout:
id: 2
Pupil{address='null', level='null', group='null', last='null', name='null'}
you should use #RequestBody
#RequestMapping(value = "/changePupil/{id}", method = RequestMethod.PUT)
public void changePupil(#PathVariable("id") Long id,#RequestBody Pupil pupil){
System.out.println("id: "+id);
System.out.println(pupil.toString());
}
Take an advantage of #RestController on your controller class instead of #Controller and specify the MediaType that your rest method consuming and you may have to register appropriate HttpMessageConverter too.
Ref: How to configure MappingJacksonHttpMessageConverter while using spring annotation-based configuration?

Can't understand `#Autowired HttpServletRequest` of spring-mvc well

In our spring application, we use HttpServletRequest in two ways:
(the code here are simplied, and seems meaningless)
In the controller:
#RequestMapping(value = "/hello", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<String> hello(HttpServletRequest request) {
System.out.println("## controller req.hashcode: " + request.hashCode());
System.out.println("## header 'abc': " + request.getHeader("abc"));
return new ResponseEntity<String>("OK", HttpStatus.OK);
}
In a normal component:
#Component
class RequestService {
private final HttpServletRequest request;
#Autowired
public RequestService(HttpServletRequest request) {
this.request = request;
}
public String getHeaderAbc() {
System.out.println("## service req.hashcode: " + request.hashCode());
return this.request.getHeader("abc");
}
}
At first, I was thinking the 2nd way is totally wrong, because it should only inject the request instance once. So no matter when I invoke getHeaderAbc() method, it should return the same value(of the first request).
But when I try it, I found several interesting things:
The request.hashCode() in controller is always different (as I expected)
The request.hashCode() in RequestService is always the same (as I thought)
But the header value is different if I issue a request with a different header abc !!!
It seems for the singleton RequestService, spring keeps the request instance, but changed the headers it contains!
How to understand it?
Take a look at the scoped proxy. http://www.java-allandsundry.com/2012/08/spring-scoped-proxy.html
Basically you inject a proxy that keeps a references to the current HttpRequest beans and gives you the right one, selecting it by the request id.
IMHO using HttpRequest outside of the web layer is not a good practice. I would use it only in the controlellrs.

Resources