I am staring working on spring boot and trying a simple Rest Controller.
I have two methods using HTTP GET and they work fine.
However when I do a HTTP POST it is not working showing :
: Request method 'POST' not supported
My Controller code as below:-
enter code here
package com.example.web.api;
import java.math.BigInteger;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.example.model.Greeting;
#RestController
public class GreetingController {
private static BigInteger nextId;
private static Map<BigInteger, Greeting> greetingMap;
private static Greeting save(Greeting greeting){
if (greetingMap==null){
greetingMap = new HashMap<BigInteger, Greeting>();
nextId = BigInteger.ONE;
}
greeting.setId(nextId);
nextId=nextId.add(BigInteger.ONE);
greetingMap.put(greeting.getId(), greeting);
return greeting;
}
static {
// First Greeting
Greeting g1 = new Greeting();
g1.setText("Hello World!!");
save(g1);
// Second Greeting
Greeting g2 = new Greeting();
g2.setText("Hola Mundo!!");
save(g2);
}
/*
*
* Issue a GET to view greetings
*
*/
#RequestMapping(
value="/api/greetings",
method=RequestMethod.GET,
produces=MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<Collection<Greeting>> getGreetings(){
Collection<Greeting> greetings=greetingMap.values();
return new ResponseEntity<Collection<Greeting>>(greetings, HttpStatus.OK);
}
/*
*
* Issue a GET to view single greeting by id value
*
*/
#RequestMapping(
value="/api/greetings/{id}",
method=RequestMethod.GET,
produces=MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<Greeting> getGreeting(#PathVariable("id") BigInteger id){
Greeting greeting = greetingMap.get(id);
if(greeting == null){
return new ResponseEntity<Greeting>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity <Greeting> (greeting, HttpStatus.OK);
}
/*
*
* Create a POST to add a greeting
*
*/
#RequestMapping(
value="/api/greetings/",
method=RequestMethod.POST,
consumes=MediaType.APPLICATION_JSON_VALUE,
produces=MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<Greeting> createGreeting(#RequestBody Greeting greeting){
Greeting savedGreeting = save(greeting);
return new ResponseEntity <Greeting> (savedGreeting, HttpStatus.CREATED);
}
/* End of HTTP Methods */
}
Kindly advise , what is wrong with createGreeting Method.
Kind regards
your POST method has a trailing slash /api/greetings/ which you missed in your curl call and the other thing you missed is a Content-type header. You should say to server what type of data you send.
curl -X POST -d '{"text":"hello"}' -H "Content-type:application/json" http://localhost:8080/api/greetings/ is a working curl call.
You need to modify the Content-Type to json
try changing link the value to another, for example:
#RequestMapping(
value="/api/greeting",
method=RequestMethod.GET,
produces=MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<Greeting> createGreeting(#RequestBody Greeting greeting){
Greeting savedGreeting = save(greeting);
return new ResponseEntity <Greeting> (savedGreeting, HttpStatus.CREATED);
}
Related
I am using some external API to GET and POST some ressources, locally my code works fine with the call of different endPoints (GET, POST...) and even with Postman, but when i try to run my code in another platerform (where the ressources are), i get the 412 HTTP error due to a POST call : after looking on the internet, i found out that i should generate an ETagd of the entity (that i went to modify) and add it into the header of my POST endPoint.
For that, i used ShallowEtagHeaderFilter and the #Bean annotation(above the filter method) and the #SpringBootApplication annotation above my class, here is my code :
package main.Runners;
import io.testproject.java.annotations.v2.Parameter;
import okhttp3.*;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.configurationprocessor.json.JSONArray;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.context.annotation.Bean;
import org.springframework.web.filter.ShallowEtagHeaderFilter;
import javax.servlet.Filter;
#SpringBootApplication
public class ActionRunner {
#Parameter(description = "the project ID")
public static String projectId = "xxx";
#Parameter(description = "the test ID")
public static String testId = "yyy";
public static void main(String[] args) throws Exception {
try {
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
Request request = new Request.Builder()
.url("https://api.testproject.io/v2/projects/"+projectId+"/tests/"+testId)
.method("GET", null)
.addHeader("Authorization", "nzmo4DI08ykizYgcp9-5cCTArlxq7k7zt9MYhGmTcRk1")
.build();
Response response = client.newCall(request).execute();
System.out.println("================ this is our response headers ::: \n"+ response.headers());
} catch(Exception e) {
System.out.println(e);
}
}
#Bean
public ShallowEtagHeaderFilter shallowEtagHeaderFilter(){
return new ShallowEtagHeaderFilter();
}
}
I really need Your help since i cant generate any ETag parameter on my GET response header(after checking reponse.headers() ).
Thanks in advance!
From this artcle, I have implemented calling another rest API from my REST API method in micronaut gradle application. Since my REST API expects jwt token I am sending the same token I received with in current request. I am seeing Unauthorized error even token is being passed. Can anyone help in this regard. Below is my code.
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpStatus;
import io.appter.clientmgmt.models.ClientContact;
import io.appter.clientmgmt.repositories.IClientContactRepository;
import io.micronaut.http.uri.UriTemplate;
import io.micronaut.security.annotation.Secured;
import io.micronaut.security.authentication.Authentication;
import io.micronaut.security.rules.SecurityRule;
import io.micronaut.http.annotation.*;
import io.micronaut.http.client.RxHttpClient;
import io.micronaut.http.client.annotation.Client;
import io.reactivex.Flowable;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import javax.validation.constraints.NotNull;
import java.security.Security;
import java.util.List;
#Controller("/clientcontact")
//#Secured(SecurityRule.IS_ANONYMOUS)
public class ClientContactController {
private static final Logger LOG = LoggerFactory.getLogger(ClientContactController.class);
private IClientContactRepository clientContactRepository;
private final RxHttpClient httpClient;
public ClientContactController(IClientContactRepository clientContactRepository,
#Client("http://appterauthsvc-env.g2yapp2kcp.us-east-1.elasticbeanstalk.com") RxHttpClient httpClient) {
this.clientContactRepository = clientContactRepository;
this.httpClient = httpClient;
}
#Get("/")
public HttpStatus index() {
return HttpStatus.OK;
}
#Post("/")
#Secured(SecurityRule.IS_AUTHENTICATED)
public ClientContact createClientContact(#Body ClientContact clientContact,
Authentication authentication,
#Header("Authorization") String authorization) {
try {
List<ClientContact> existingClientContacts = clientContactRepository.getClientContactByClientId(clientContact.getClientId());
LOG.info("current contacts count for the client " + clientContact.getClientId() + " is " + existingClientContacts.size());
if (existingClientContacts.isEmpty()) {
User userObj = new User();
Long clientId = new Long(clientContact.getClientId());
userObj.setClientId(clientId);
userObj.setFirstName(clientContact.getFirstName());
userObj.setLastName(clientContact.getLastName());
userObj.setEmailId(clientContact.getEmailAddress());
userObj.setPhoneNo(clientContact.getContactNumber());
userObj.setIsActive(true);
LOG.info("User Email set is: "+userObj.getEmailId());
LOG.info("authorization token is: "+authorization);
HttpRequest<?> request = HttpRequest.POST("/user", userObj).bearerAuth(authorization);
String response = httpClient.toBlocking().retrieve(request);
LOG.info("Request Object: "+ request.toString());
LOG.info("Response Object: "+ response.toString());
LOG.info("User API executed.. ");
}
return clientContactRepository.createClientContact(clientContact);
} catch (Exception ex) {
LOG.error(ex.getMessage(), ex);
return null;
}
}
}
Thanks in advance.
Likely because #Header("Authorization") String authorization is returning something like Bearer xyz... and the bearerAuth method is adding Bearer to the string so you are sending Bearer Bearer xyz...
So just do .header(HttpHeaders.AUTHORIZATION, authorization)
Also as a side note you really shouldn't be doing blocking HTTP calls in this method. It's not the end of the world since in this case you're blocking an IO thread, however this type of code should be avoided.
I configure the RESTFul API in JPOS from jpos-rest.pdf.
The problem is I couldn't receive data from the client, but I can send data to the client.
In Echo.java class by below code I can send data:
package org.jpos.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.HashMap;
import java.util.Map;
#Path("/echo")
public class Echo {
#GET
#Produces({MediaType.APPLICATION_JSON})
public Response echoGet() {
Map<String, Object> resp = new HashMap<>();
resp.put("success", "true");
resp.put("Name", "Hamid");
resp.put("Family", "Mohammadi");
Response.ResponseBuilder rb = Response.ok(resp, MediaType.APPLICATION_JSON).status(Response.Status.OK);
return rb.build();
}
}
How can I receive data from the client? There is no request parameter to find what is the request and its data;
Thanks to #Sabir Khan
I changed the code to:
#Path("/echo")
public class Echo {
#PUT
#Produces({MediaType.APPLICATION_JSON})
#Consumes(MediaType.TEXT_PLAIN)
#Path("/{name}/{family}")
public Response echoGet(
#PathParam("name") String name,
#PathParam("family") String family,
String Desc
) {
Map<String, Object> resp = new HashMap<>();
resp.put("success", "true");
resp.put("Name", name);
resp.put("Family", family);
resp.put("Desc", Desc);
Response.ResponseBuilder rb = Response.ok(resp,
MediaType.APPLICATION_JSON).status(Response.Status.OK);
return rb.build();
}
}
and send data to RESTFul API like this:
When I want to test REST application, I try to write a test code segment like below:
Controller Code:
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
#RestController
#RequestMapping(value="/Test")
public class test {
#RequestMapping(value="test1/{modelId}",method = RequestMethod.POST)
public void test1(#PathVariable(value="modelId") String modelId, #RequestBody MultiValueMap<String, String> values){
String name = values.getFirst("name");
String description = values.getFirst("description");
System.out.println(modelId);
System.out.println(name);
System.out.println(description);
}
#RequestMapping(value="test2",consumes="application/x-www-form-urlencoded",method = RequestMethod.PUT)
public void test2( #RequestBody MultiValueMap<String, String> values){
String name = values.getFirst("name");
String description = values.getFirst("description");
System.out.println(name);
System.out.println(description);
}
}
and below is Ajax call function:
function start() {
var data1 = "test";
var data2 = "test model";
var jdata = {name:data1,description:data2};
$.ajax({
type: "PUT",
async: false,
url: "/Test/test2",
dataType: "json",
contentType: "application/x-www-form-urlencoded;charset=UTF-8",
data: jdata,
success: function (data) {
alert("ok");
}
});
}
I can get the right result when i call http://localhost:8080/Test/test1/123.
but when i try to call http://localhost:8080/Test/test2,the console display warning:
WARN o.s.w.s.m.support.DefaultHandlerExceptionResolver - Failed to read HTTP message:
org.springframework.http.converter.HttpMessageNotReadableException:
Required request body is missing:
public void com.wisto.util.test.test2(org.springframework.util.MultiValueMap<java.lang.String, java.lang.String>)
and the browser get 400 error.
I think I must miss something about config of SpringBoot. How can I solve it?
For More clearer,I put a True Code From Activiti
package org.activiti.rest.editor.model;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* #author Tijs Rademakers
*/
#RestController
public class ModelSaveRestResource implements ModelDataJsonConstants {
protected static final Logger LOGGER = LoggerFactory.getLogger(ModelSaveRestResource.class);
#Autowired
private RepositoryService repositoryService;
#Autowired
private ObjectMapper objectMapper;
#RequestMapping(value="/model/{modelId}/save", method = RequestMethod.PUT)
#ResponseStatus(value = HttpStatus.OK)
public void saveModel(#PathVariable String modelId, #RequestBody MultiValueMap<String, String> values) {
try {
Model model = repositoryService.getModel(modelId);
ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
modelJson.put(MODEL_NAME, values.getFirst("name"));
modelJson.put(MODEL_DESCRIPTION, values.getFirst("description"));
model.setMetaInfo(modelJson.toString());
model.setName(values.getFirst("name"));
repositoryService.saveModel(model);
repositoryService.addModelEditorSource(model.getId(), values.getFirst("json_xml").getBytes("utf-8"));
InputStream svgStream = new ByteArrayInputStream(values.getFirst("svg_xml").getBytes("utf-8"));
TranscoderInput input = new TranscoderInput(svgStream);
PNGTranscoder transcoder = new PNGTranscoder();
// Setup output
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
TranscoderOutput output = new TranscoderOutput(outStream);
// Do the transformation
transcoder.transcode(input, output);
final byte[] result = outStream.toByteArray();
repositoryService.addModelEditorSourceExtra(model.getId(), result);
outStream.close();
} catch (Exception e) {
LOGGER.error("Error saving model", e);
throw new ActivitiException("Error saving model", e);
}
}
}
The Code above works well with Spring.But with SpringBoot.So I am confused!
I don't think your data object is converted to a string as the payload.
Try:
data:JSON.stringify(jdata)
Also content type should be:
contentType: "application/json; charset=utf-8"
Change the dataType parameter in ajax. Your code is specifying data type is JSON but controller is get as application/x-www-form-urlencoded
You can make it dataType: 'text'
Or if you use JSON for the request Then change the following
in controller consumes=MediaType.APPLICATION_JSON_VALUE
in ajax parameter contentType: "application/json"
I am very new to Spring and I am having trouble getting anything back from a rest service. I would love to get an answer to what I am doing wrong. Thanks in an advance!
This is the rest service from where I am trying to get an answer:
Here is my code.
package testi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
#SpringBootApplication
public class TestiApplication {
public static void main(String[] args) {
SpringApplication.run(TestiApplication.class, args);
}
public void run(String... args) throws Exception {
RestTemplate restTemplate = new RestTemplate();
//Asetettaan otsikkotietueet
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("X-ESA-API-KEY", "ROBOT");
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
System.out.println("Testing " + entity.getHeaders());
String answer = restTemplate.postForObject("https://www.veikkaus.fi/api/v1/sport-games/draws?game-names=MULTISCORE", entity, String.class);
System.out.println(answer);
//ResponseEntity<String> response = restTemplate.exchange("https://www.veikkaus.fi/api/v1/sport-games/draws?game-names=MULTISCORE", HttpMethod.GET, entity, String.class);
//System.out.println(response);
}
}
The API documentation you provided seems to indicate the API you're trying to access uses the GET method. You are making the request with the POST method (restTemplate.postForObject(...)).
Try using the GET method via restTemplate.getForObject(...).
In general, when debugging your REST calls, you should also examine the response status code in addition to the response body. In this case this arguably would have yielded the HTTP 405 error indicating what went wrong.