This is a test case I was writing for update calls to database:
#Test
public void testUpdateList() {
//
//... Some variables
//
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
String requestBody = "{\"id\":\"" + givenId + "\",\"listName\":\"" + listName + "\",\"owner\":\"" + owner + "\"}";
HttpEntity <String> entity = new HttpEntity<>(requestBody, headers);
// Call to update
ResponseEntity <TaskListResponse> list = template.exchange(REQUEST_URL + "/list/update/{id}", HttpMethod.PUT, entity, TaskListResponse.class, params);
}
Here params is a name-value HashMap for the REST URL.
When I wanted to update a list type, since RestTemplate.put() doesn't have a return type, I used HTTP requests.
A call with template.put would look like this:
template.put(REQUEST_URL + "/list/update/{id}", request, params);
But I don't know the difference between the two types of calls. Could someone explain it to me in reference to the above code? How can template.exchange return a value, if it's a PUT request?
What I'm looking for is that since I used template.post/get/delete for create(), search() and delete(), should I use .put() for update() as well, even though I won't get a response?
Related
I am working with Redmine API, and want to update an issue.
The issue has 30 variables, Subject, Description, Author, and Assignee ...
I have no problem updating the issue Subject and Description like this:
#RequestMapping(value = "/issues/update/{id}", method = RequestMethod.PUT)
public ResponseEntity<Object> issueUpdate(#RequestBody ObjectNode json, #PathVariable int id) throws RedmineException, RuntimeException, IllegalArgumentException {
String apiKey = json.get("API_KEY").asText();
RedmineManager mgr = RedmineManagerFactory.createWithApiKey("http://localhost:3001/", apiKey);
IssueManager issueManager = mgr.getIssueManager();
Issue issue = issueManager.getIssueById(id);
issue.setSubject(json.get("SUBJECT").asText())
.setDescription(json.get("DESCRIPTION").asText())
.update();
return new ResponseEntity<>(HttpStatus.OK);
}
The problem with this way is I am only allowed to change these 2 values and I have to include, SUBJECT and DESCRIPTION in my JSON request body.
If SUBJECT is not in JSON, then it will be considered as null and I get NullPointerException.
I want to make something more flexible and elegant, to allow the change of each value, and if not exist, don't set to null but keep the old values.
something logical to this but a bit smarter
if json.get("SUBJECT").asText() != null {
issue.setSubject(json.get("SUBJECT").asText()) //set if mentioned
} else {
issue.setSubject(issue.getSubject()) //set the old value
}
The idea is, now am available to have setSubject and all the other available setters in case it's mentioned in my JSON request or not.
I am building a formData
const formulario = new FormData();
formulario.append('preco', this.formularioCasaVenda.get('preco').value);
formulario.append('foto_1', this.formularioCasaVenda.get('foto_1').value);
formulario.append('dormitorios', this.formularioCasaVenda.get('dormitorios').value);
I am sending it in a post request.
const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'multipart/form-data'})
};
return this.http.post<Casa>("http://localhost:8080/api/casas-venda", formData1).pipe(
tap((product: Casa) => console.log(`added product w/ id=$`)),
catchError(this.handleError<Casa>('addProduct'))
);
How can I access dormitorios, foto_1, preco from the Spring boot controller, so I can populate a model?
My "desperate" atempt.
#CrossOrigin(origins = "http://localhost:4200")
#PostMapping("casas-venda")
public CasaVenda storeCasaVenda(#RequestParam("formulario") MultipartFile[] casaVenda){
CasaVenda casaVendaDB = new CasaVenda();
casaVendaDB.setDormitorios(1);
casaVendaDB.setPreco( Double.parseDouble(casaVenda[1].toString()));
casaVendaDB.setPreco(900.00);
return casaVendaDB;
// return this.casaVendaRepositorio.save(casaVenda);
}
This is one way of solving it:
#CrossOrigin(origins = "http://localhost:4200")
#PostMapping("/casas-venda")
public CasaVenda storeCasaVenda(#RequestParam("dormitorios") Integer dormitorios,
#RequestParam("preco") BigDecimal preco,
#RequestParam("foto_1") MultipartFile foto) {
CasaVenda casaVendaDB = new CasaVenda();
casaVendaDB.setDormitorios(dormitorios);
casaVendaDB.setPreco(preco.doubleValue());
// foto I am assuming is a file, so you receive it and you have to get the InputStream from it.
return casaVendaDB;
// return this.casaVendaRepositorio.save(casaVenda);
}
One hint:
Don't return in the endpoints #Entity classes, it is not a nice practice, instead you should create a DTO (Data Transfer Object) and only return to the Frontend what they need to know.
https://martinfowler.com/eaaCatalog/dataTransferObject.html
I hope I could help you.
I'm trying to send a httpClient.get request with params and consume it in my Spring Controller. I want to send search criteria and return a list of objects according to that criteria.
This is my search.service.ts
public getDentists(name, city, type, rating): Observable<Dentist[]>{
let params = new HttpParams();
params.set('name', name);
params.set('city', city);
params.set('type', type);
params.set('rating', rating);
return this.httpClient.get('dentists/', {params: params});
}
in my controller.java
#RequestMapping(value = "/dentists", method = RequestMethod.GET)
public List<Dentist> search(#RequestParam("name") String name,
#RequestParam("city") String city,
#RequestParam("type") String type,
#RequestParam("rating") String rating) {
return dentistRepository.findDentistByName(name);
}
This is what I get as an error:
I also get this error:
2017-12-03 01:07:10.138 WARN 10108 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'name' is not present
My question is what am I doing wrong, why am I not receiving the params with requestparam?
HttpParams is immutable. All the mutation operators return a new instance, so you have to do
let params = new HttpParams()
.set('name', name)
.set('city', city)
.set('type', type)
.set('rating', rating);
or
let params = new HttpParams();
params = params.set('name', name);
params = params.set('city', city);
params = params.set('type', type);
params = params.set('rating', rating);
change your code to:
let params = new HttpParams()
.set('name', name)
.set('city', city)
.set('type', type)
.set('rating', rating);
HttpParams is immutable.
try to use append() method (instead of add()):
public getDentists(name, city, type, rating): Observable<Dentist[]>{
let params = new HttpParams();
params = params.append('name', name);
params = params.append('city', city);
params = params.append('type', type);
params = params.append('rating', rating);
return this.httpClient.get('dentists/', {params: params});
}
UPDATE
actually append() and set() methods will produce exactly the same result:
?name=NAME_VALUE&city-CITY_VALUE&type=TYPE_VALUE&rating=RATING_VALUE,
append() should be used when we want to append another value to existing key, something like:
?name=NAME1&name=NAME2_VALUE&.....
We also can use HttpParamsOptions object passed to HttpParams constructor:
const params = new HttpParams({
fromObject: {
name,
city,
type,
rating
}
});
return this.httpClient.get('dentists/', {params});
I am new in spring and learning RedirectAttributes.Below is th sample code I am executing.
#RequestMapping(value="/")
public String app(Model model,RedirectAttributes rm) throws IOException{
UserCO userCO= new UserCO();
userCO.setEmail("rptdbay#gmail.com");
rm.addFlashAttribute("flashkey", "flashvalue");
rm.addFlashAttribute("userCO", userCO);
return "redirect:/controller1";
}
#RequestMapping(value="/controller1")
public String app1(Model model,HttpServletRequest request) throws IOException{
System.out.println("=====================================");
System.out.println("In Controller 1");
Map md = model.asMap();
for (Object modelKey : md.keySet()) {
Object modelValue = md.get(modelKey);
System.out.println("Model data =="+ modelKey + " -- " + modelValue);
}
java.util.Enumeration<String> reqEnum = request.getParameterNames();
while (reqEnum.hasMoreElements()) {
String s = reqEnum.nextElement();
System.out.println("Request data =="+ s+" : "+ request.getParameter(s));
}
return "redirect:/controller2";
}
#RequestMapping(value="/controller2")
public String app2(Model model,HttpServletRequest request) throws IOException{
System.out.println("=====================================");
System.out.println("In Controller 2");
Map md = model.asMap();
for (Object modelKey : md.keySet()) {
Object modelValue = md.get(modelKey);
System.out.println("Model data =="+ modelKey + " -- " + modelValue);
}
java.util.Enumeration<String> reqEnum = request.getParameterNames();
while (reqEnum.hasMoreElements()) {
String s = reqEnum.nextElement();
System.out.println("Request data =="+ s+" : "+ request.getParameter(s));
}
return "redirect:/controller3";
}
I have added String "flashvalue" and a object of bean userCO.I observed that-
Both "flashvalue" and userCO are available in Controller1.
Fine!,but in Controller2 "flashvalue" is available but userCO
not .Why so?
In Controller1 data is coming in Model ony but in Controller2 same
data is availavble in request only.Why so?
Below is my console log.
=====================================
In Controller 1
Model data ==userCO -- com.ttnd.mvc_mod.co.UserCO#60098260
Model data ==flashkey -- flashvalue
=====================================
In Controller 2
Request data ==flashkey : flashvalue
Is there any other way possible to get FlashAttribute rather than binding in Model?
First the explanation of your console log: You receive two model objects in controller 1. This is because you specify two flash attributes in method app. Flash attributes are stored in the HTTP session for the target controller, which retrieves it from there as model attributes. After that the flash attributes are erased by Spring.
In controller 2 the flash attributes are no longer available. The reason why “flashkey” is available in controller 2 as request attribute is, since primitive types in models are exposed as query parameters to the redirect target. As mentioned before, the flash attributes passed to controller 1 are exposed as model attributes. Your “userCO” is no primitive type, so you it will not get it as request parameter, while you will get “flashkey” as query parameter in controller 2.
If you want to switch off the “forward” of model objects as request parameters, set org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.setIgnoreDefaultModelOnRedirect(boolean) to true (as suggested by Spring for ‘new’ applications).
I don’t know whether there is another way to get flash attributes. I’d encourage you to not work around the concepts of Spring here but handle the flash attributes just like you did in your question. Think of flash attributes as model attributes in your redirect target. If you – for what reason – need two redirect until you reach your target, add the desired attributes a second time as flash attributes in controller 1.
See http://docs.spring.io/spring/docs/4.1.7.RELEASE/spring-framework-reference/html/mvc.html#mvc-ann-redirect-attributes and http://docs.spring.io/spring/docs/4.1.7.RELEASE/spring-framework-reference/html/mvc.html#mvc-flash-attributes for any details.
Can someone help me convert the following from Java to C# (Xamarin)?
I tried a couple of different ways, but I cannot get it to work.
The code is:
HttpPost post = new HttpPost(url);
// Break out all extra HTTP header lines and add it to the HttpPost object
for (String line : contentType.replace("\r", "\n").split("\n")) {
if (line.length() > 0 && line.contains(":")) {
String[] parts = line.split(":", 2);
if (parts.length == 2) {
post.addHeader(parts[0].trim(), parts[1].trim());
}
}
}
// Create a byte array entity for the POST data, the content
// type here is only used for the postEntity object
ByteArrayEntity postEntity = new ByteArrayEntity(challenge);
postEntity.setContentType("application/octet-stream");
post.setEntity(postEntity);
// Create a HttpClient and execute the HttpPost filled out above
HttpClient client = new DefaultHttpClient();
HttpResponse httpResponse = client.execute(post);
// Get the response entity out of the response
HttpEntity entity = httpResponse.getEntity();
If you are stuck with
post.SetEntity(postEntity);
then it converts to:
ByteArrayEntity postEntity = new ByteArrayEntity(challenge);
postEntity.SetContentType("application/octet-stream");
post.Entity = postEntity;
When converting to Java from C# you mostly have to change the property names to start with upperCase and then if you get stuck on certain objects I would look check out the Xamarin API Docs, HttpPost class linked here.