CORDA Start Flow through HTTP Endpoint - java

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());
}
}

Related

Troubles posting a JSON value using Spring Boot

I am trying to make a post request using json but in postman the request is successful only if I make the request like this: email#example.com. If I make a request using the standard JSON format {"email":"email#example.com"} I get "invalid email id". I should mention that content type application/json header is checked in postman, and I am making the request in body/raw.
I have tried messing with #RequestBody/#RequestParam annotations, using consumes = "application/json" but I am unsuccessful and I couldn't find a similar issue after lots of googling either.
my controller:
#RestController
public class UserController {
#Autowired
private UserService userService;
#PostMapping(value = "/forgot-password", consumes = "application/json")
public String forgotPassword(#RequestBody String email) {
String response = userService.forgotPassword(email);
if (!response.startsWith("Invalid")) {
response = "http://localhost:8080/reset-password?token=" + response;
}
return response;
}
user service:
public String forgotPassword(String email) {
Optional<User> userOptional = Optional
.ofNullable(userRepository.findByEmail(email));
if (!userOptional.isPresent()) {
return "Invalid email id.";
}
User user = userOptional.get();
user.setToken(generateToken());
user.setTokenCreationDate(LocalDateTime.now());
user = userRepository.save(user);
return user.getToken();
}
Simply put, the #RequestBody annotation maps the HttpRequest body to a transfer or domain object.You need to put object instead of String
Your endpoint should be like Below.
#PostMapping(value = "/forgot-password", consumes = "application/json")
public String forgotPassword(#RequestBody EmailDto email) {
String response = userService.forgotPassword(email.getEmail);
// ...
return response;
}
Your DTO should be like below
public class EmailDto {
private String email;
//Getters and Setters
}
You should have Email model with string property email.
public EmailPayload {
String email;
.....
Then it will work (it will fit json you provided).
Ofcouse class name can be different, only thing that must match is email property, then in your Controller your #RequestBody will be this class, and not String you have now.

Form application encoded value is not working in spring rest

I have the below post request and of which below is the controller code
#RestController
#RequestMapping(/flow", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
#Override
#ResponseStatus(HttpStatus.OK)
#PostMapping("{abcCode}/token")
public TokenResponse createToken(#PathVariable("abcCode") String abcCode,
#RequestParam("grant_type") String grantType,
#RequestParam String code,
#RequestParam("redirect_uri") String redirectUri,
#RequestParam String clientId) {
LOG.info(
"Received call for createIdToken for abcCode: {} , clientId: {} , grantType: {} ,code: {} , redirectUri: {}",
abcCode, clientId, grantType, code, redirectUri);
}
Now the problem is that when I test the same above controller through postman by choosing the body type as application form-encoded then it is working fine but when I choose the body type as none in postman and just pass the above request parameters as query one then also it works which ideally it should not please advise how can I overcome from the same
http://localhost:19080/testService/flow/token?grant_type=authorization_code&code=3272&redirect_uri=http://www.abchui.com&clientId=ATS
it should not work for the above URL
From spring sources:
public static final String APPLICATION_FORM_URLENCODED_VALUE = "application/x-www-form-urlencoded";
According to docs, when using url-form-encoded data pass as query params.
Try to change form mime type.

How to request origin and body of a request in Spring controller

I'm building a REST API using Java and Spring and I need to handle a POST request in my controller, but I need to extract the body from that request which is a JSON and also the "origin" of that request,
#RequestMapping(value = "/create", method = RequestMethod.POST)
public XXX createMyObject(#RequestBody String data, YYY){
MyObject mo = new MyObject();
mo.setData = data;
mo.setOrigin = yyy;
myRepository.save(mo);
return XXX;
}
I have a few questions: First is how can I obtain the origin of that request( which I guess is an url that travels in the header?), is there a similar annotation as the #RequestBody for that?.
My second question is what is usually the proper object to return in these kind of post methods as a response.
To answer your questions:
If you include HttpServletRequest in your method parameters you will be able to get the origin information from there. eg.
public XXX createMyObject(#Requestbody String data, HttpServletRequest request) {
String origin = request.getHeader(HttpHeaders.ORIGIN);
//rest of code...
}
For rest responses you will need to return a representation of the object (json) or the HttpStatus to notify the clients whether the call wass successful or not. eg
Return ResponseEntity<>(HttpStatus.ok);
You should be able to get headers and uris from HttpServletRequest object
public XXX createMyObject(#RequestBody String data, HttpServletRequest request)
As for response I'd say return String which would be a view name to which you can pass some attributes saying that operation was successful or not, or ModelAndView.
#Autowired
private HttpServletRequest servletRequest;
You can declare request object and then access in method to get Uri
Try this:
#RequestMapping(value = "/create", method = RequestMethod.POST)
public XXX createMyObject(HttpServletRequest request, #RequestBody String body) {
String origin = URI.create(request.getRequestURL().toString()).getHost();
System.out.println("Body: " + body + " Origin:" + origin);
return XXX;
}

How do I retrieve query parameters in a Spring Boot controller?

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

Spring MVC forwarding HTTP POST request to GET request handler in another controller

I am trying to get my controller to forward a POST request to another controller with some parameters:
#RequestMapping(method=RequestMethod.POST)
public String processSubmit(#Valid Voter voter, BindingResult result,
//...
request.setAttribute("firstName", voter.getFirstName());
request.setAttribute("lastName", voter.getLastName());
request.setAttribute("ssn", voter.getSsn());
logger.info("VoterID exists, forwarding to /question/prepare");
return "forward:/question/prepare";
The problem that I am facing is that /question/prepare points to a Controller method that handles only HTTP GET requests.
#RequestMapping(value="/prepare", method=RequestMethod.GET)
public String prepareVoterBean(#RequestParam String firstName,
#RequestParam String lastName, #RequestParam String ssn, Model model) {
logger.info("QuestionController got GET REQUEST for " + firstName + lastName + ssn);
VoterBean bean = new VoterBean();
bean.setFirstName(firstName);
bean.setLastName(lastName);
bean.setSsn(ssn);
model.addAttribute("questions",bean);
return "questionPage";
}
Is there a way to forward the request to prepareVoterBean as a HTTP GET request? Thanks.
Is there a way to forward the request to prepareVoterBean as a HTTP
GET request?
Try using redirect: prefix.
return "forward:/question/prepare";
This is not POST. The following link might be useful: "22.5.3 Redirecting to views" section.
#Midnight Blue...
Change return type to return "forward:/prepare";

Categories