I am developing a project using Spring Boot. I've a controller which accepts GET requests.
Currently I'm accepting requests to the following kind of URLs:
http://localhost:8888/user/data/002
but I want to accept requests using query parameters:
http://localhost:8888/user?data=002
Here's the code of my controller:
#RequestMapping(value="/data/{itemid}", method = RequestMethod.GET)
public #ResponseBody
item getitem(#PathVariable("itemid") String itemid) {
item i = itemDao.findOne(itemid);
String itemname = i.getItemname();
String price = i.getPrice();
return i;
}
Use #RequestParam
#RequestMapping(value="user", method = RequestMethod.GET)
public #ResponseBody Item getItem(#RequestParam("data") String itemid){
Item i = itemDao.findOne(itemid);
String itemName = i.getItemName();
String price = i.getPrice();
return i;
}
While the accepted answer by afraisse is absolutely correct in terms of using #RequestParam, I would further suggest to use an Optional<> as you cannot always ensure the right parameter is used. Also, if you need an Integer or Long just use that data type to avoid casting types later on in the DAO.
#RequestMapping(value="/data", method = RequestMethod.GET)
public #ResponseBody
Item getItem(#RequestParam("itemid") Optional<Integer> itemid) {
if( itemid.isPresent()){
Item i = itemDao.findOne(itemid.get());
return i;
} else ....
}
To accept both #PathVariable and #RequestParam in the same /user endpoint:
#GetMapping(path = {"/user", "/user/{data}"})
public void user(#PathVariable(required=false,name="data") String data,
#RequestParam(required=false) Map<String,String> qparams) {
qparams.forEach((a,b) -> {
System.out.println(String.format("%s -> %s",a,b));
}
if (data != null) {
System.out.println(data);
}
}
Testing with curl:
curl 'http://localhost:8080/user/books'
curl 'http://localhost:8080/user?book=ofdreams&name=nietzsche'
In Spring boot: 2.1.6, you can use like below:
#GetMapping("/orders")
#ApiOperation(value = "retrieve orders", response = OrderResponse.class, responseContainer = "List")
public List<OrderResponse> getOrders(
#RequestParam(value = "creationDateTimeFrom", required = true) String creationDateTimeFrom,
#RequestParam(value = "creationDateTimeTo", required = true) String creationDateTimeTo,
#RequestParam(value = "location_id", required = true) String location_id) {
// TODO...
return response;
#ApiOperation is an annotation that comes from Swagger api, It is used for documenting the apis.
To accept both Path Variable and query Param in the same endpoint:
#RequestMapping(value = "/hello/{name}", method = RequestMethod.POST)
public String sayHi(
#PathVariable("name") String name,
#RequestBody Topic topic,
//#RequestParam(required = false, name = "s") String s,
#RequestParam Map<String, String> req) {
return "Hi "+name +" Topic : "+ topic+" RequestParams : "+req;
}
URL looks like : http://localhost:8080/hello/testUser?city=Pune&Pin=411058&state=Maha
I was interested in this as well and came across some examples on the Spring Boot site.
// get with query string parameters e.g. /system/resource?id="rtze1cd2"&person="sam smith"
// so below the first query parameter id is the variable and name is the variable
// id is shown below as a RequestParam
#GetMapping("/system/resource")
// this is for swagger docs
#ApiOperation(value = "Get the resource identified by id and person")
ResponseEntity<?> getSomeResourceWithParameters(#RequestParam String id, #RequestParam("person") String name) {
InterestingResource resource = getMyInterestingResourc(id, name);
logger.info("Request to get an id of "+id+" with a name of person: "+name);
return new ResponseEntity<Object>(resource, HttpStatus.OK);
}
See here also
Related
I have this rest controller method in springboot
#GetMapping("/cghsHcoSearchText/cityId/{cityId}/hcoName/{hcoName}/treatmentName/{treatmentName}")
public String cghsHcoSearchText(#PathVariable String cityId, #RequestParam(name = "hcoName", required = false) String hcoName,
#RequestParam(name = "treatmentName", required = false) String treatmentName) {
return "Some Text";
}
It has one PathVariable and 2 optional Request parameter.
Now when I hit this url with treatmentName = null i get Whitelabel Error Page
http://localhost:8082/cghs/cghsHcoSearchText/cityId/011?hcoName=Guru?
Any help will be appreciated.
We should not specify request param as a placeholder in URL mapping. Only the path params should be mentioned in placeholder. Sharing a code snippet and corresponding URL which will help out in understanding this
#GetMapping("hello/{id}")
public ResponseEntity<Void> printInfo(#PathVariable("id") String id,
#RequestParam(required = false, name = "name") String name) {
System.out.println(id + " " + name);
return new ResponseEntity<>(HttpStatus.OK);
}
Here id comes as a path param and name as a request param which is not mentioned in mapping annotation.
URL would look like
http://localhost:8080/hello/234?name=pappi
I am trying to issue flow through HTTP endpoint. Basically I wan t to create a webserver where I can start a flow by passing some values to the http request. The parameters passed in the http query are the values for the State object along with the name of the owner (otherParty).
#RequestMapping(value = "/issue/{make}/{model}/{year}/{mile}/{vin}/{owner_name}", method = RequestMethod.GET)
#ResponseBody
private String issueCar(#PathVariable String make, #PathVariable String model, #PathVariable int year, #PathVariable float mile, #PathVariable String vin, #PathVariable String owner_name){
CordaX500Name ownerName = new CordaX500Name(owner_name, "New York", "US");
Party owner = this.proxy.wellKnownPartyFromX500Name(ownerName);
System.out.println(owner);
this.proxy.startFlowDynamic(CarRegistrationFlowInitiator.class,make, model,year,mile,vin,owner);
return "Flow Successful";
}
I am currently unable to do so. Am I missing anything here?
Try to follow the implementation of the controller with this CorDapp: https://github.com/corda/samples-java/blob/master/Accounts/tictacthor/clients/src/main/java/com/tictacthor/webserver/Controller.java
It is doing similar url Post calls as what you are trying to do there. Be sure to check if your server port and rpc port are correctly configured.
#PostMapping(value = "requestGameWith/{whoAmI}/{team}/{competeWith}")
private ResponseEntity<String> requestGameWith(#PathVariable String whoAmI,#PathVariable String team, #PathVariable String competeWith){
Set<Party> matchingPasties = proxy.partiesFromName(team,false);
try{
Iterator iter = matchingPasties.iterator();
String result = proxy.startTrackedFlowDynamic(ShareAccountTo.class,whoAmI,iter.next()).getReturnValue().get();
return ResponseEntity.status(HttpStatus.CREATED).body("Game Request has Sent. When "+competeWith+" accepts your challenge, the game will start!");
}catch (Exception e) {
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(e.getMessage());
}
}
Requirement: I have a POST method which takes the input JSON as a String and passes it to another microservice. I don't want to create an Object (Bean) of this input JSON.
method:
#ApiOperation(notes = "example" value = "/example", consumes = ".." , method= "..")
#RequestMapping(name = "xxx" value ="/hello" ..)
#ApiResponses(..)
public #ResponseBody String getXXX (#Apiparam(name="JSONrequest", required = true) #RequestBody String JSONrequest){
}
Problem:
The generated Swagger doesn't show the input as a JSON model where all the JSON attributes are displayed.
Expectation:
I want to display my Swagger Something like this :
Definately I am missing the key thing. Any thoughts?
If changing from String to a concrete object is not okay (although that's what I would recommend you to do since it's cleaner), you can try using #ApiImplicitParams (check out their documentation)
#ApiOperation(notes = "example" value = "/example", consumes = ".." , method= "..")
#ApiImplicitParams({
#ApiImplicitParam(name = "Object", value = "Object to be created", required = true, dataType = "your.package.BodyClass", paramType = "body")
})
#RequestMapping(name = "xxx" value ="/hello" ..)
#ApiResponses(..)
public #ResponseBody String getXXX (#Apiparam(name="JSONrequest", required = true) #RequestBody String JSONrequest){
}
(not sure if you still need the #Apiparam(name="JSONrequest", required = true) bit from the method parameter)
It's an old question but since I haven't found a solution online here how I to customized the example value in the swagger documentation produce automatically by the java annotations.
I use swagger 2.0 and springfox.version 2.10.5.
The Idea is documenting the class of the request parameter that has the #RequestBody annotation. for example my method is
#ApiOperation(
value = "Start ListBuilder extraction",
response = ExtractionLogEntity.class,
produces = "application/json"
)
#PostMapping("/extraction/start")
public ExtractionLogEntity startTask(
#RequestBody(required = true) ExtractionRequest request,
In order to expose request json object example I added a #ApiModelProperty(example = "...") annotation to the properties of ExtractionRequest .
#ApiModelProperty(example = "[{ 'field':'value'}]")
#NotNull
private List<ListBuilderFieldEntity> fields;
#ApiModelProperty(example = "1000")
private String ied;
#ApiModelProperty(example = "US")
private String codebase;
And that's the result
I had the similar issue. My Service Class takes #RequestBody argument in String.
So, what I did :
Created a POJO and used #RequestBody annotation with it instead of inputString.
#RequestMapping(value = "/api/entity/{entityId}/user/query", method = {RequestMethod.POST}, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
ResponseEntity<String> queryUser(#PathVariable("entityId") String entityId,
#RequestBody QueryUserJsonSchemaPOJO queryUserJsonSchemaPOJO, String inputString,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
return userService.queryUserService(inputString, entityId, request);
}
Created an AOP with #Around annotation which update the inputString argument.
#Around(value = "execution(* com.athmin.rest.UserController.*(..)) || execution(* com.athmin.rest.CityController.*(..)), and args(..) " +
" && #annotation(com.athmin.annotations.JSONSchemaFileName) ")
public Object validateRequestBodyAgainstJsonSchema(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object[] modifiedArgs = proceedingJoinPoint.getArgs();
for (Object o : proceedingJoinPoint.getArgs()) {
if (o instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = (HttpServletRequest) o;
requestBody = httpServletRequest.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
}
});
for (int i = 0; i < modifiedArgs.length; i++) {
if (modifiedArgs[i] == null) { // Only inputString is null in my case
modifiedArgs[i] = requestBody;
}
}
proceedingJoinPoint.proceed(modifiedArgs);
}
Here is the code for the controller
#RequestMapping(value = "/fetchRecord/", method = RequestMethod.POST)
#ResponseBody
public String fetchRecord(Integer primaryKey)
{
return this.serviceClass.fetchRecord(primaryKey);
}
Here is my angular code
var dataObj = {
primaryKey : $scope.primaryKey
};
var res = $http.post('/Practice/learn/fetchRecord/', dataObj);
res.success(function(data, status, headers, config) {
$scope.firstname = data;
});
res.error(function(data, status, headers, config) {
alert("failure message: " + JSON.stringify({
data : data
}));
});
i am able to debug my code. Although i can check it in browser that value for primaryKey get passed. But still it is null in controller.
any possible reason for that ?
You should send a json object,
try this,
var dataObj = {
primaryKey : $scope.primaryKey
};
var res = $http.post('/Practice/learn/fetchRecord/', angular.toJson(dataObj));
You can get the value in the Controller from two ways:
First option:
Assign an object that has the attribute you want to pass.
Suppose that you have RecordEntity object, it has some attributes, one of them is the Integer primaryKey. The annotation #RequestBody will receive the value, so the controller will be:
backend
#RequestMapping(value = "/fetchRecord/", method = RequestMethod.POST)
#ResponseBody
public String fetchRecord(#RequestBody RecordEntity recordEntity) {
return "primaryKey from requestBody: " + recordEntity.getPrimaryKey();
}
frontend
In the frontend you should send an json that has the primaryKey attribute in the body, for example:
http://localhost:8080/Practice/learn/fetchRecord/
Post body:
{
"primaryKey": 123
}
You controller will receive the value in the RecordEntity object.
Second option:
Pass the value by URL, the annotation #RequestParam will receive the value, so the controller will be:
backend
#RequestMapping(value = "/fetchRecord", method = RequestMethod.POST)
#ResponseBody
public String fetchRecord(#RequestParam Integer primaryKey) {
return "primaryKey from RequestParam: " + primaryKey;
}
frontend
In the url you should send the value with ?primaryKey, for example
http://localhost:8080/Practice/learn/fetchRecord?primaryKey=123
You controller will receive the value in the Integer primaryKey.
Hello i'm new in implementing Spring REST Web Service what's the cause of my error.
Here's my code
#RequestMapping(value = "/message/{regID}/name/{name}", method = RequestMethod.GET, headers = "Accept=application/json")
public String getMessage(#PathVariable String regID, #PathVariable String name) {
return "Hello Alvin!" + regID + " " + name;
}
i want to call it using the web browser but i failed to successfully invoke it but when i call single parameter of may another RequestMapping is Successfully completed.. Here is the RequestMapping that i successfully called
#RequestMapping(value = "/country/{id}", method = RequestMethod.GET, headers = "Accept=application/json")
public Country getCountryById(#PathVariable int id) {
List<Country> listOfCountries = new ArrayList<Country>();
listOfCountries = createCountryList();
for (Country country : listOfCountries) {
if (country.getId() == id)
return country;
}
return null;
}
Or How can i implement multiple parameter for my RequestMapping..?
The chances are that you're using the InternalResourceViewResolver, in which case the methods that return String will interpret the returned valued as a view name that will be searched inside the locations designated in the view resolver. Your no mapping found probably refers to that the framework can't find a view name that matches what you're returning
As your intention seems to be to return the text only you should simply additional map your method with #ResponseBody which will in turn add your text to response body instead of interpreting it as a view name, so
#ResponseBody
public String getMessage(#PathVariable String regID, #PathVariable String name)
Otherwise, your mapping is just fine
I you have more than one path variables, you need to sepecify the identifier in #PathVariable:
#RequestMapping(value = "/message/{regID}/name/{name}", method = RequestMethod.GET, headers = "Accept=application/json")
public String getMessage(#PathVariable("regID") String regID, #PathVariable("name") String name) {
return "Hello Alvin!" + regID + " " + name;
}