Spring ControllerAdvice how to return Json or html page according to Accept request header? - spring

Now, App can return a cutstom 404 page.
#ControllerAdvice
class GlobalControllerExceptionHandler {
#ResponseStatus(HttpStatus.NOT_FOUND)
#ExceptionHandler(NoHandlerFoundException.class)
public String handle404(WebRequest request) {
return "/exceptions/404";
}
}
And I wonder how should I do, if I want to get a JSON when Accept request header is Accept: application/json, like this:
$> curl -H "Accept: application/json" http://localhost:8080/no-such-page
{"timestamp":"2018-04-11T05:56:03.845+0000","status":404,"error":"Not Found","message":"No message available","path":"/no-such-page"}```

Related

Spring Integration - http inbound

im trying to make a http inbound but when i print my message the payload its empty, what am i missing here?
#Slf4j
#Component
public class HttpInboundGateway {
#Bean
public IntegrationFlow inGate1() {
log.info("Initializing inbound gateway...");
return IntegrationFlows.from(Http.inboundChannelAdapter("/")
.requestPayloadType(PayloadObj.class))
.channel("transfer_next_channel")
.get();
}
#Bean
#ServiceActivator(inputChannel = "transfer_next_channel")
public MessageHandler handler() {
return new MessageHandler() {
#Override
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println("myHandlerPayload: " + message.getPayload());
System.out.println("myHandlerHeader: " + message.getHeaders());
}
};
}
}
PayloadObj class expected:
#Data
#NoArgsConstructor
public class PayloadObj {
String name;
String job;
}
EDIT 1: As requested
Curl from Postman
curl --location --request GET 'http://localhost:9090/' \
--header 'Content-Type: application/json' \
--data-raw '{
"name":"Marcos",
"job":"Dev Jr"
}'
Print from handler:
myHandlerPayload: {} --- Payload
myHandlerHeader: {content-length=46, http_requestMethod=GET,
host=localhost:9090, http_requestUrl=http://localhost:9090/,
connection=keep-alive, id=e67aef3d-938a-7ac3-eb7d-ddaf9cd74f4e,
contentType=application/json;charset=UTF-8, accept-encoding=gzip,
deflate, br, user-agent=PostmanRuntime/7.28.4, accept=*/*,
timestamp=1642168826837}
curl --location --request GET 'http://localhost:9090/'
You do GET request. This way the body of the request is ignored.
And only request params are transferred as payload. Since you don't have those as well, that means the payload is empty Map.
Consider to use POST or PUT instead.
And learn more about an HTTP protocol and its method specifics.

how to send a single String to a RestAPI endpoint using CURL

I have a #RestController with an endpoint that receives a single String :
#RestController
public class ScriptController {
private Logger logger = LoggerFactory.getLogger(ScriptController.class);
public ScriptController(Engine engine) {
this.engine = engine;
}
#RequestMapping(value = "/run", method = RequestMethod.POST)
public Object run(#RequestBody String script){
return engine.run(script);
}
}
when I send a request to this endpoint using CURL :
curl --request POST localhost:9999/run --data-binary "testObj.hi()"
I am not receiving the exact String ("testObj.hi()") in the Controller, instead I receive the following one :
testObj.hi%28%29=
what is the problem?
when I change the method from POST to GET (in both sides) it works! but I want to use POST method.
By default, the request body is URL encoded in HTTP requests, and since there is no content-type header, spring boot doesn't decode the encoded characters.
Specifying Content-Type header will solve the problem, something like this:
curl --request POST localhost:8080/run --data-binary "testObj.hi()" -H 'Content-Type: text/utf-8'
It works in case of GET requests because parameters are expected to be URL encoded in case of GET request and they are decoded by the spring.

HTTP Status - 401 Unauthorized

I'm trying to convert from curl to java code with intention to call an API to create a token but I get a 401 response.
Curl code:
curl -X POST \
https://apigw.dev/commercial/oauth/create-token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'client_id=dfdfdfdfd&client_secret=dfdfdf&grant_type=client_credentials'
And here my java code:
#RestController
public class TokenController {
#RequestMapping(value = "/getAccessToken", method = RequestMethod.POST)
public ClientCredentialsResourceDetails getAccessToken(ClientCredentialsResourceDetails resource) throws Exception {
resource.setAccessTokenUri(tokenUri);
resource.setClientId(clientId);
resource.setClientSecret(clientSecret);
resource.setGrantType("client_credentials");
resource.setClientAuthenticationScheme(AuthenticationScheme.header);
resource.setScope(Arrays.asList("read", "write"));
System.out.println(resource);
return resource;
}
}
and here the results:
"timestamp": "2020-04-28T14:02:28.381+0000",
"status": 401,
"error": "Unauthorized",
"message": "Unauthorized",
"path": "/getAccessToken"
}
I really appreciate your suggestion, Thanks in advance.
You're making a POST request with CURL, but your rest controller is configured as GET. I guess you have another endpoint to /getAccessToken with POST method wich requires the token.
Also, by default, every mehod in a #RestController class will consume an application/json and produce an application/json.
If your request is a Content-Type: application/x-www-form-urlencoded, change the consume type of your request to MediaType.APPLICATION_FORM_URLENCODED_VALUE.

Parse request parameters without writing wrapper class

How to handle json requests and parse the request parameters in dropWizard?
#POST
#Path("/test")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public String test(#Context final HttpServletRequest request) {
JSONObject data=new JSONObject();
System.out.println(request);
System.out.println(request.getParameterMap());
System.out.println(">>>>>>>>>");
return "{\"status\":\"ok\"}";
}
I wrote the above code and tried the following request.
curl -XPOST -H "Content-Type: application/json" --data {"field1":"val1", "field2":"val2"} http://localhost:8080/test
But request.getParameterMap() is {}
How to parse the parameters without writing a wrapper class?
Your curl command may need some additional quotes around the data (I'm getting an error without them):
curl -H "Content-type: application/json" -X POST -d '{"field1":"tal1", "field2":"val2"}' http://localhost:8080/test
You are sending a POST request without URL parameters. I'm not sure why you are expecting to see something there.
I don't know which version of dropwizard you are using but I couldn't make the combination of #POST and #Path("/something") annotation to behave when a method is annotated. I'm getting HTTP ERROR 404.
To make it work I have to move the #Path annotation to the resource/class level and leave only the #Post annotation at the method.
#Path("/test")
public class SimpleResource {
#POST
#Consumes(MediaType.APPLICATION_JSON)
public String test(final String data) throws IOException {
System.out.println("And now the request body:");
System.out.println(data);
System.out.println(">>>>>>>>>");
return "{\"status\":\"ok\"}";
}
}
To get the body of the request as String just do as above. Taken from here: How to get full REST request body using Jersey?
The console looks like:
INFO [2016-11-24 15:26:29,290] org.eclipse.jetty.server.Server: Started #3539ms
And now the request body:
{"field1":"tal1", "field2":"val2"}
>>>>>>>>>

Unsupported Media Type in jersey RESTfull api

I am trying to build a RESTfull API using the Jersey library but it gives me an exception.
Here is my Docs class
#XmlRootElement
#XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
public class Docs {
#XmlElement(name = "field")
public String field;
#XmlValue
public String content;
}
#Path("/update")
public class Update {
#POST
#Path("/xml")
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public String createIndexXML(Docs docs)
throws Exception {
System.out.println(docs.content);
return "It works";
}
}
If I try to check it using CURL it throws Error 415 Unsupported Media Type
curl -XPOST "http://localhost:8089/update/xml" -d '<docs>
<field>title</field>
</docs>'
You need to add the content type to your request header. Add -H "Content-Type: application/xml" to yourcurl` call.
I think you're also going to find that there are problems with your annotations on your bean - but that's another issue...
This should work:
curl -H "Content-Type: application/xml"
-X POST -d "<docs><field>title</field></docs>" "http://localhost:8089/update/xml"
You should also try Accept: application/xml; watch out for defining both #Produces and #Consumes! See Using #Consumes and #Produces to Customize Requests and Responses.

Resources