I need to return something into Response class format but I have an SAMLResult variable so when I get the Status (ResponseStatus) I don't find any way to parse it to a Responsevariable.
Has someone any idea how to do this ?
If i understand your problem correctly, you are only interested in the numeric SAMLResponse status and need to return this as a new value of type Response.
So you can simply build a new Response with the SAMLResponse status value:
int samlStatus = SAMLResponse.ResponseStatus;
Response response = Response.status(samlStatus).build();
return response;
Or you can intantiate a new Response object (by implementing all methods from the abstract Response class e.g. with default values) and set the SAMLResponse.ResponseStatus value in the getStatus() method. For example:
Response response = new Response() {
#Override
public int getStatus() {
int samlStatus = SAMLResult.ResponseStatus;
return samlStatus;
}
// override all other Response methods ...
}
return response;
Related
I have an endpoint where it supposes to sends a string as a response. My question is do I need to use to response Entity to send string response or just return the string to the consumer?
#GetMapping(value = "/word")
public String getWord() {
String response = "webservice";
return response;
}
Second approach:
#GetMapping(value = "/word", produces ={MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<String> getWord() {
String response = "webservice";
return new ResponseEntity<>(response, HttpStatus.OK);
}
What is the correct approach to send just a string or use response entity?
What is the correct approach to send just a string or use response entity?
The Spring MVC documentation lists a number of types that can be returned from controller methods.
As I previously answered here and here, ResponseEntity<T> represents the entire HTTP response. Besides the body, its API allows you to set headers and a status code to the response.
Returning just a bean instance or a string is fine but doesn't give you much flexibility: In the future, if you need to add a header to the response or modify the status code, for example, you need to change the method return type.
I need to set different HTTP Status code for my REST webservice request.
Basically user will send ISBN number , I need to validate it
if user send empty request body , give error message ISBN cannot be empty
and set http status code
if user gives Alphabets , Given error message Alphabets not allowed and set http status code appropriate
if user gives wrong format, Give error message wrong format and set different HTTP status code.
if isbn is not valid, Give error message Not a Valid ISBN number and set appropriate HTTP status code.
If Valid ISBN number then return book name with http status as 200.
I tried setting http status code but its not reflecting.
#RequestMapping(value = "/person", method = RequestMethod.POST,
consumes = "application/json", produces = "application/json")
public ResponseEntity<StatusBean> findBook(#RequestBody String json) {
StatusBean sb = new StatusBean();
if(json==null) {
sb.setMessage("Request Cannot be Null");
return new ResponseEntity<StatusBean>(sb,HttpStatus.BAD_REQUEST);
}
if(!isNumeric(json)) {
sb.setMessage("Request Cannot have Alphabets Characters");
//here i need to set different status
return new ResponseEntity<StatusBean>(sb,HttpStatus.BAD_REQUEST);
}
if(!isValidFormat(json)) {
sb.setMessage("Request Cannot have Alphabets Characters");
//here i need to set different status
return new ResponseEntity<StatusBean>(sb,HttpStatus.BAD_REQUEST);
}
if(!isValidISBN(json)) {
sb.setMessage("Request Cannot have Alphabets Characters");
//here i need to set different status
return new ResponseEntity<StatusBean>(sb,HttpStatus.BAD_REQUEST);
}
Map<String,String> map = new HashMap<>();
map.put("book", "Effective Java");
sb.setResponseJSONMap(map);
return new ResponseEntity<StatusBean>(sb,HttpStatus.OK);
}
public class StatusBean {
private String message;
private Map<String,String> responseJSONMap;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Map<String, String> getResponseJSONMap() {
return responseJSONMap;
}
public void setResponseJSONMap(Map<String, String> responseJSONMap) {
this.responseJSONMap = responseJSONMap;
}
}
One of the most elegant solutions is the following:
You can throw a custom exception in case of a validation error, like this:
#RequestMapping(...)
public ResponseEntity<StatusBean> findBook(#RequestBody String json) throws Exception {
...
if(json==null) {
throw new NullRequestException();
}
if(!isNumeric(json)) {
throw new RequestContainsAlphabetsException();
}
if(!isValidFormat(json)) {
throw new InvalidFormatException();
}
...
}
And then you need to define an own, global exception handler at application level. In this custom exception handler, you will catch the thrown exceptions and send back a proper response to clients with a custom error message, an HTTP response code, a timestamp, etc.
For more details see this page.
#RequestMapping(value = "/person", method = RequestMethod.POST,
consumes = "application/json", produces = "application/json")
public ResponseEntity<StatusBean> findBook(#RequestBody(required=false) String json) {
// rest of the code
}
try using (required=false) with request body. Spring requires resuest body by default.
I'm working on a POC i need to use zuul as a sever to route 2 routes first will run normally but it has a custom post filter which will send another request to other api using some data of the response of the first requet,
so need to extract the response body of the first request into my custom post filter and get some specific attributes but i can not find the response as it always be null but the status code is 200.
how can i wait and get a value of specific attribute from the response and get the actual status code not just 200 as default value.
i tried to make this implementation using cloud gateway but i reached the same point of disability of extracting the response.
also i tried to make a response decorator but it failed too.
#Component
public class AddResponseHeaderFilter extends ZuulFilter {
#Override
public String filterType() {
return "post";
}
#Override
public int filterOrder() {
return 1;
}
#Override
public boolean shouldFilter() {
return true;
}
#Override
public Object run() {
System.out.println("this is my filter");
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = new HttpServletRequestWrapper(context.getRequest());
System.out.println(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
HttpServletResponse servletResponse = context.getResponse();
// return an address only
System.out.println(context.getResponseBody().toString());
servletResponse.addHeader("X-Foo", UUID.randomUUID().toString());
return null;
}
}
RequestContext.getCurrentContext().getResponseDataStream() works fine for me, I am also able to manipulate the response.
import java.nio.charset.Charset;
import org.springframework.util.StreamUtils;
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String requestLog = StreamUtils.copyToString(request.getInputStream(),
Charset.forName("UTF-8"));
I have this endpoint method:
#RequestMapping(value = "/update")
public ResponseEntity(Response) update(
#ApiParam(required=true) #Valid #RequestBody Request request,
#RequestHeader #HeaderParam("key") String key
){
//execution of code here
return null;
}
I'm currently validating the Request Body using a custom JSON Deserializer.
Is there anyway that I could validate the Header Param "key" similar to the way I would validate a Request Body using a JSON Deserializer?
Maybe something like this that would execute before the "//execution of code here":
#Override
public String deserialize(String key){
if(!key.equals("ABC")){
throw new Exception("key is wrong");
}
return key;
}
Thank you!
Is there anyway to force spring to always produce json, even an empty json object if there's no data to return.
Our services go through another service that rejects any response that isn't valid json (regardless of status code). It's not nice but we have no control of this.
With spring controllers you can tell them to produce json, but this only works when there's content to return. Is there a quick and elegant way to make all responses be json?
#RequestMapping(value = "/test", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public
#ResponseBody
ResponseEntity<String> test(){
// if this returns null or an empty string the response body will be emtpy
// and the content-type header will not be set.
return service.getData();
}
The simply fix here is to simply add an if statement to check for null. But that's ugly as I'll have to manually set the header and the response body.
I'm hoping someone knows of a nicer way?
Thanks
If you want all responses to return application/json, then you can set this at a single place by overriding postHandle() from HandlerInterceptorAdapter:
#Component
public class ResponseInterceptor extends HandlerInterceptorAdapter {
#Override
public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler,
final ModelAndView modelAndView) throws IOException {
if (response.getContentType() == null || response.getContentType().equals("")) {
response.setContentType("application/json");
}
}
}
You can look here
You may wrap the response in a "Container" object
For example I use this BaseAjaxResponse:
public class BaseAjaxResponse implements Serializable
{
private static final long serialVersionUID = 9087132709920851138L;
private int codiceOperazione;
private String descrizioneEsitoOperazione;
private long numeroTotaleOggetti;
private long numeroOggettiRestituiti;
private List<? extends Object> payload;
//Constructors and getter/setter
}
Then in my controllers I use this strategy:
#RequestMapping(method = { RequestMethod.POST }, value = { "/find" })
public ResponseEntity<BaseAjaxResponse> createCandidato(#RequestBody CandidatoDto candidato){
BaseAjaxResponse bar = new BaseAjaxResponse();
HttpStatus statusCode = null;
List<Object> payload = null;
StopWatch sw = new StopWatch("Find");
try
{
sw.start();
payload = myService.find();
sw.stop();
if( payload == null || payload.isEmpty() )
{
statusCode = HttpStatus.NO_CONTENT;
bar.setCodiceOperazione(statusCode.value());
bar.setDescrizioneEsitoOperazione("No result");
}
else
{
statusCode = HttpStatus.OK;
bar.setCodiceOperazione(statusCode.value());
bar.setDescrizioneEsitoOperazione("Got result");
//Set the object count and the number of found objects
}
}
catch (Exception e)
{
String message = "Errore nell'inserimento di un candidato; "+e.getMessage();
statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
bar.setCodiceOperazione(statusCode.value());
bar.setDescrizioneEsitoOperazione(message);
logger.error(message, e);
}
finally
{
if( sw.isRunning() )
{
sw.stop();
if( logger.isDebugEnabled() )
{
logger.debug("CHIUSURA STOPWATCH FORZATA. "+sw.toString());
}
}
}
return new ResponseEntity<BaseAjaxResponse>(bar, statusCode);
}
I hope this can be useful
Angelo