I need to forward from a POST to a GET request.
Somehow I end up in an endless loop. It always goes to the POST handler. Of course GET and POST have the same URL . But that's normal in REST design.
So how can I forward to the GET handler. Also in the error case I need to have redirectAttributs to have the error attributes available in the GET method .
That is my code.
#RequestMapping(value = "/user/holiday", method = RequestMethod.GET)
public String holiday(Model model) {
model.addAttribute("holiday", new Holiday());
model.addAttribute("edit", false);
List<Holiday> lstHoliday = holidayDao.findByUser(userDao.findByUserName(Util.getLoggedInUserName()));
model.addAttribute("Util", new Util());
model.addAttribute("holidaylist", lstHoliday);
model.addAttribute("residualLeave",Util.calculateResidualHoliday(lstHoliday));
return "/user/holiday";
}
#PostMapping(value = "/user/holiday")
public String holidayPost(Model model, Holiday holiday,RedirectAttributes redirectAttrs) throws ParseException {
DateTimeFormatter df = DateTimeFormatter .ofPattern("dd-MM-yyyy");
holiday.setDate(Calendar.getInstance().getTime());
holiday.setFirstDay(new SimpleDateFormat("dd-MM-yyyy").parse(holiday.getStringFirstDay()));
holiday.setLastDay(new SimpleDateFormat("dd-MM-yyyy").parse(holiday.getStringLastDay()));
holiday.setNumberOfDays(Util.calculateNumberOfDays(holiday.getFirstDay(), holiday.getLastDay()));
holiday.setUser(userDao.findByUserName(Util.getLoggedInUserName()));
List<Holiday> lstHoliday = holidayDao.findByUser(userDao.findByUserName(Util.getLoggedInUserName()));
if(holiday.getNumberOfDays()> Util.calculateResidualHoliday(lstHoliday))
{
redirectAttrs.addAttribute("hasError", true);
redirectAttrs.addAttribute("errorMessage", "Die Anzahl an Urlaubstagen ist größer als Ihr Resturlaub !!");
return "forward:/user/holiday";
}
holidayDao.save(holiday);
return "redirect:/user/holiday";
}
The funny thing is , the redirect works when the holiday can be saved. It only does not work when there is an error so it is in the if block.
Related
I've set up a route that when I get a name in my post body I will search the DB and return an ID value.
What I want to do is once there is no ID present in the DB return a 204 status code.
But should that be handled in the service or in my controller?
and
How do I return my specific status code?
#ResponseStatus(HttpStatus.OK)
#PostMapping("/ID_values/")
fun getID(
#RequestBody
name: String
): ResponseEntity<String> = ResponseEntity.ok(IDLookupService.lookupIDValue(name))
}
#Service
class EmailLookupService(
private val IDRepo: IDRepo
) : Logging {
fun lookupIDValue(name: String): String {
val IDLookupResult = IDRepo.findById(name)
return if (IDLookupResult.isPresent) {
IDLookupResult.get().ID.toString()
} else {
// return status code 204
}
}
}
First, you should omit the #ResponseStatus(HttpStatus.OK) annotation if you do not wish to always return a status code of 200. Using that annotation, it would suffice to only specify the response body as return value (i.e specify return type String and then return only result in your example), and Spring would automatically wrap that into a response entity with HTTP-status OK.
Second, you need some way to tell the caller of IDLookupService.lookupIDValue (which should probably be called on an instance of IDLookupService and not the class itself) that there was nothing found. This could be done for instance by changing the return type to String? and return null if nothing was found.
Then you can change getID to return
val result = idLookupService.lookupIDValue(name)
return if(result != null) ResponseEntity.ok(result)
else ResponseEntity("not found", HttpStatus.NO_CONTENT)
If you wish to return something different than a String in the case there was nothing found (like an error object with detailed information; in the example here it is simply the text "not found"), you can change the response type of getID to ResponseEntity<*>.
I use Spring Boot rest api with MongoDB.
In the POST Method, if there is not scoreID and there is not a player with specific date in my collection, because at the same time a player cannot play different games and bring score, then if the specific player and gamecode exist, create a score.
In fact, in the POST Method I used Nested IF-ELSE conditions.
But, in the Postman when I execute POST Request with this data:
{
"scoreid":"s11",
"score":1000,
"player":"sahari",
"gamecode":"g12",
"date":"2020-01-01"
}
always, I recieve an error, in the Postman, 400 Bad Request!, which i defined in the last line of my IF-ELSE statements.
I do not know, what is my mistake and why my program doese not execute IF conditions correct.
The POST Method:
//Create Score
#PostMapping
public ResponseEntity<?> createScore(#RequestBody #JsonView(Views.class) #Valid Score score) {
String p = srepo.findByPlayerName(score.getPlayer());
String g = srepo.findByGameCode(score.getGamecode());
String scoreid = srepo.findByScoreid(score.getScoreid());
Query query = new Query();
query.addCriteria(new Criteria().andOperator(Criteria.where("player").is(score.getPlayer()),
Criteria.where("date").is(score.getDate())));
if((scoreid != null)) {
return ResponseEntity.status(409).body("Conflict!"); }
else
if(mongoTemplate.exists(query, Score.class))
return ResponseEntity.status(409).body("There is not Possible at same time one player brings different Scores!");
else
if((p!= null)&&(g!= null))
{
history = new ArrayList<History>();
h = new History();
h.setScore(score.getScore());
h.setDate(score.getDate());
history.add(h);
hrepo.save(h);
score.setHistory(history);
srepo.insert(score);
return ResponseEntity.ok(score);
}
else
{
return ResponseEntity.status(400).body("Bad Request!");
}
}
The Score Repository:
#Repository
public interface ScoreRepository extends MongoRepository<Score, String>{
#Query("{'scoreid':?0}")
public String findByScoreid(String scoreid);
#Query("{'Player.nickname':?0}")
public String findByPlayerName(String player);
#Query("{'Games.code':?0}")
public String findByGameCode(String game);
}
The problem is not for my IF-ELSE statements.The problem is in the Score Repository
I must return a List instead of String for findByPlayerName and findByGameCode and for findByScoreid which is for checking duplicate in the POST Method I must return type of Score
I am trying to follow Rest Principles, so I have two rest controllers
with a base URL localhost:8088/trucks.
First, I have to get all trucks:
#GetMapping(value = "/trucks")
public final Collection<TruckDto> getAllTrucks() {
LOGGER.debug("test: getAllTrucks()");
Collection<Truck> trucks = truckService.getAllTrucks();
return mappingService.map(trucks, TruckDto.class);
}
Note, my issue also has to do with the fact that I have different classes I am returning for truckById and truckByTruckCode.
And I have 'get truck by ID' service:
#GetMapping(value = "/trucks/{truckId:[0-9]+}")
#ResponseStatus(HttpStatus.FOUND)
#ResponseBody
public final TruckDto getTruckId(#PathVariable(value = "truckId") final Integer truckId) {
LOGGER.debug("test: truckId({})", truckId);
Truck truck = truckService.getTruckById(truckId);
return mappingService.map(truck, TruckDto.class);
}
Now I have a get by truckCode that works but it doesnt follow the rest principle , which is something like , there should be only one base url and all others build from it , here it is
#ResponseStatus(HttpStatus.OK)
#ResponseBody
#GetMapping(value = "/trucks/{truckCode:[0-9]*[a-zA-Z][a-zA-Z0-9]*}")
public final TruckWithAvgPetrolDto getTruckByTruckCode (#PathVariable(value = "truckCode")
final String truckCode) {
LOGGER.debug("getTruckByTruckCode()");
TruckWithAvgDto truck = truckService.getTruckByTruckCode(truckCode);
return mappingService.map(truck, TruckWithAvgPetrolDto.class);
}
Now it works but I think it should be an optional param there for it should be in one method. So maybe I can have some sort of optional return type because I have two different services, methods to return in both situations.
Because get by id just gets truck detail, but get by trukCode performs a left join and gets truck average consumption of petrol from an order table so I have two different DTOs for get by id and get by truckCode.
My questions are how can I get something like one method say getBY(param) if I put a number it should get by id and return TruckDto but if I put a code like BY788 it should get by code and return a TruckWithAvgPetrolDto. Is that's possible?
This is a solution that works but i will need verification that it is ok to do such in rest or it is bad practice
#GetMapping("/trucks/{value}")
public ResponseEntity<?> getTruckByIdOrCode(#PathVariable(value = "value" )String value) {
if (value.matches("[0-9]*[a-zA-Z][a-zA-Z0-9]*")) {
TruckWithAvgDto list = truckService.getTruckByTruckCode(value);
return new ResponseEntity<TruckWithAvgDto>(list, HttpStatus.FOUND);
}else {
Truck truck = truckService.getTruckById(Integer.parseInt(value));
return new ResponseEntity<Truck>(truck,HttpStatus.FOUND);
}
}
Im sending request from salesforce to laravel then laravel return the result and display them on visual force page
Error Detail
Apex Method
public List<SelectOption> getItems()
{
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();
req.setEndpoint('http://clozer.3spire.net/public/goclozer/country');
req.setMethod('GET');
req.setCompressed(false);
req.setBody('key1=value1&key2=value2');
req.setHeader('Content-Type', 'application/json');
try {
res = http.send(req);
} catch(System.CalloutException e) {
system.debug('Callout error: '+ e);
}
getAllCountry = (Map<String, String>)JSON.deserialize(res.getBody(),Map<String, String>.class);
List<SelectOption> option = new List<SelectOption>();
option.add(new SelectOption('0','--None--'));
for(String c : getAllCountry.values())
{
option.add(new SelectOption(c,c));
}
return option;
}
Expected Result
{"0":"Aruba","1":"Antigua and Barbuda","2":"United Arab Emirates","3":"Afghanistan","4":"Algeria","5":"Azerbaijan","6":"Albania","7":"Armenia","8":"Andorra","9":"Angola","10":"American Samoa","11":"Argentina","12":"Australia","13":"Ashmore and Cartier Islands"}
Laravel 5 Route
Route::get('/goclozer/country','GoClozerController#getCountry');
Laravel 5 Method
public function getCountry()
{
$country = \App\Country::all();
$names = array();
foreach($country as $c)
{
$names[] = $c->name;
}
echo json_encode($names,JSON_FORCE_OBJECT);
}
How can i get ride of this error
Thanks in advance
MethodNotAllowedHttpException means that you're using wrong HTTP verb ( Get, Post, Put, Delete ...). You've route defined for GET, but you may be posting data
The modification (as I assume you just want to retrieve the country names only) can be achieved by
$countries = Country::all(['name']);
this will only retrieve the names of the countries from the table, you can add more fields if you want to.
Controller gets a request, returns a response. You're not returning any response. just echoing the result. You can do the following,
return $countries;
This will simply return the JSON with country names.
You don't have to put an explicit slash at the front of route declaration. you can even write like the following and that will work too.
Route::get('goclozer/country','GoClozerController#getCountry');
I am using Spring MVC in my project and while mapping user request to a URI, I get the 404 error. Here is my function skeleton which I want to be invoked:
#RequestMapping(value="/inventory/discovery", method = RequestMethod.GET, params = {"discoveryType"}, produces = {"application/json"})
public String getDiscoveryByType(#RequestParam("discoveryType") String discoveryType)
{
return discoveryType;
}
I am expecting this method to be called when I give the URL
http://<some-ip>/inventory/discovery/discoveryType?=DMVPN
However, when I test the code using Chrome's Advanced Rest Client I see that the URI it is trying to access is "/inventory/DMVPN" and not the "/inventory/discovery?discoveryType=DMVPN".
Am I missing something here? I don't see anything wrong with my URL syntax
I have another function in my code (but I don't think it is causing the problem) which has same request-mapping value, but has no params attribute.
#RequestMapping(value = "/inventory/discovery", method = RequestMethod.GET, produces = { "application/json" })
public ResponseEntity<DiscoveryNIOListResult> getAllDiscovery() {
logger.trace("getAllDiscovery");
List<DiscoveryNIO> listDiscoveryNIO = discoveryDasClient.getDiscoveryList();
DiscoveryNIOListResult result = new DiscoveryNIOListResult();
result.setResponse(listDiscoveryNIO);
return new ResponseEntity<DiscoveryNIOListResult>(result, HttpStatus.OK);
}
Ok, so a second look at your URL:
http://<some-ip>/inventory/discovery/discoveryType?=DMVPN
This is NOT passing discoveryType as a request GET parameter. For that you would need to do:
http://<some-ip>/inventory/discovery&discoveryType?=DMVPN
If you want to use path variables instead, you could do something like:
http://<some-ip>/inventory/discovery/DMVPN
And change your handler to something like:
#RequestMapping(value="/inventory/discovery/{discoveryType}", method = RequestMethod.GET, produces = {"application/json"})
public String getDiscoveryByType(#PathVariable("discoveryType") String discoveryType)
{
return discoveryType;
}
It looks like you were trying to mix these two methods, and that wont work.
Try changing your URL to:
http://<some-ip>/inventory/discovery?discoveryType=DMVPN