How to validate the response of my java service in angular? - java

I have a Java service that queries the database and returns a list of data which I must show in a table in my front with angular, so I did this method that returns a hash map to know if an error occurred when querying or to know that there is no data in the date range so it returns an error code since I want to validate this code in the front and show a message in my front that there is no data or that an error occurred in addition to showing the
Java Controller
#CrossOrigin(origins = "http://localhost:4200")
#RestController
#RequestMapping("/consultValues")
public class ValuesController {
#GetMapping
public Map<String, Object> consultValues(
#RequestParam(required = false, value = "startDate") Integer startDate,
#RequestParam(required = false, value = "endDate") Integer endDate) throws Exception {
Map<String, Object> listValues = new HashMap<>();
try {
listValues = valuesService.listValues(startDate, endDate);
} catch (Exception e) {
LOGGER.error("Error in Values ");
throw e;
}
return listValues;
}
}
Java Service
#Override
public Map<String, Object> listValues(Integer startDate, Integer endDate) throws Exception {
Map<String, Object> response = new HashMap<>();
List<ValuesDto> list = new ArrayList<ValuesDto>();
try {
Integer start = startDate;
Integer end = endDate;
list = valuesRepository.findByDates(start, end);
if (list.isEmpty() || list == null) {
LOGGER.error("There is not values");
response.put("Error", 400);
}
} catch (Exception e) {
LOGGER.error("An error ocurred");
response.put("Error", 500);
response.put("error", e.getMessage());
throw e;
}
response.put("success", true);
response.put("data", list);
return response;
}
Now in my front I have this method of my service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import {ValoresDto} from '../Models/ValoresDTO';
#Injectable({
providedIn: 'root'
})
export class ConsultValuesService {
constructor(private http: HttpClient) { }
Url = 'http://localhost:8080/consultValues';
consultValues(startDate:any, endDate:any){
return this.http.get<ValuesDTO[]>(this.Url+ `?startDate=${startDate}&endDate=${endDate}`);
}
}
In my Component.ts I have this method but I dont know how to validate the response of my java service, for example if my java service returns a code error 400 means that there is not data and show a message with Swal, if returns 500 ocurred an error and show the message with Swal too, or sucees return the list and fill my table
getValuesDB() {
if (this.valuesForm.valid) {
this.service.consultValues(this.endDate, this.endDate).subscribe({
next: data => {
this.modelConsultValues=data;
},
error: (err) => console.error(err),
complete: () => console.log('Completed')
});
} else {
Swal.fire({
icon: 'error',
text: 'You must select both dates'
})
}
}
anyone helps me please, how can I validate the response of my java service and show the table fill or the messages

This is highly opinionated but I will post a link anyway. class-validator let's you spice up models with decorators and then validate the instances.
https://github.com/typestack/class-validator

Related

Parse String API response containing GeoJson FeatureCollection to Angular and add them as pins with pop-up info on leaflet map

Below is the service method (JsonObjectBuilderService) that converts an object (FeatureCollectionForGeoJson) to a jsonStr. This service method is used in the Get RequestMapping to send a response to the front-end.
The FeatureCollectionForGeoJson object is a class mapped for GeoJson FeatureCollection.
The GeometryForGeoJson is another class that contains the string type with "Point" value and the array that contains the latitude and longitude for the point.
The PropertyForGeoJson class contains information/properties about that pin that will be displayed in the pop-up when the pin is clicked on on the map.
#Getter
#Setter
#ToString
#NoArgsConstructor
#AllArgsConstructor
public class FeatureForGeoJson {
private final String type = "Feature";
private GeometryForGeoJson geometry;
private PropertyForGeoJson properties;
}
#Service
public class JsonObjectBuilderService {
public String transformObjectToGeoJson(FeatureCollectionForGeoJson featureCollectionForGeoJson){
ObjectMapper Obj = new ObjectMapper();
String jsonStr = null;
try {
jsonStr = Obj.writeValueAsString(featureCollectionForGeoJson);
} catch (JsonProcessingException e) {
e.printStackTrace();
} //catch (IOException e) {
return jsonStr;
}
}
This is the GetMapping that sends the response to Angular
#GetMapping("/power-plants")
public ResponseEntity<String> getAllPowerPlants() {
try {
FeatureCollectionForGeoJson powerPlantsToFeatureCollectionForGeoJson ;
//jpa query for the database to return the information
List<PowerPlant> powerPlantList = powerPlantJpaService.findAll();
if (powerPlantList.isEmpty()) {
logger.info("The power plant list is empty.");
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
logger.info("The power plant list is populated and has been returned successfully.");
powerPlantsToFeatureCollectionForGeoJson = transformPowerPlantsToFeaturesCollection.transformPowerPlantToGeoJsonElements(powerPlantList);
String objectToGeoJson = jsonObjectBuilderService.transformObjectToGeoJson(powerPlantsToFeatureCollectionForGeoJson);
logger.info(objectToGeoJson);
return new ResponseEntity<>(objectToGeoJson, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
This is how the response looks like in the browser
This is the Angular method that fetches the response.
This is the Angular component where I call the service method that fetches the response and where I want to add the pins to the map with the pop-ups.
How do I take that response from the API (line 27 from Home.component.ts -right above- or the getAll() method from the PowerPlantService) and process it to extract the Point Geometry, to create a pin with it and extract the properties to add to a pop-up to the pin?
if you use angular you should use Observables and not Promises, also avoid to post images of code, now I can't copy/paste you code.
what you want to do is return an observable in getAll(), something like this:
// in component
this.powerPlantService.getAll$().subscribe(
res => this.featureCollection = res,
err => console.log(err)
);
// in service
getAll$(): Observable<any[]> {
return this.http.get(baseUrl).pipe(
map(data => {
// transform your data here, or remove this pipe if you don't need it
return data;
})
);
}
you can transform your features in a flat object like this:
return this.http.get(baseUrl).pipe(
map(features => {
return features.map(f => {
const pointGeometry: any = {
...f.geometry,
...f.properties
};
return pointGeometry;
});
})
);
If you want to know how the back end formats and sends the response, please check in the body of the question.
Below is the service method that performs a GET request to the back end.
export class PowerPlantService {
constructor(private http: HttpClient) { }
getAll() {
return this.http.get(baseUrl);
}
Below is the component method that subscribes to the answer and adds the elements to the map.
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
private latitude: number = 45.6427;
private longitude: number = 25.5887;
private map!: L.Map;
private centroid: L.LatLngExpression = [this.latitude, this.longitude];
ngOnInit(): void {
this.initMap();
}
constructor(private powerPlantService: PowerPlantService) {
}
private initMap(): void {
this.map = L.map('map', {
center: this.centroid,
zoom: 2.8
});
const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{
minZoom: 2.8,
attribution: '© OpenStreetMap'
});
tiles.addTo(this.map);
this.powerPlantService.getAll().subscribe((data: any)=>{
console.log(data);
L.geoJSON(data).addTo(this.map)
})

why jpa not save data at a time

i want save data and check the data after call save method
but the value is not present in same request
i have two method depend each other
the two function communcation with each other by kafka
the first method save the data and after save using jpa call second method
find the recourd from database using jpa
and check the instanse using isPresent()
but in the second method i cant find the data save
but after this request i can find data
return exciption NoSuchElement
Try out several ways like:
1-use flush and saveAndFlush
2-sleep method 10000 milsec
3-use entityManger with #Transactional
but all of them not correct
i want showing you my two method from code:
i have producer and consumer
and this is SaveOrder method (first method):
note : where in the first method have all ways i used
#PersistenceContext
private EntityManager entityManager;
#Transactional
public void saveOrder(Long branchId,AscOrderDTO ascOrderDTO) throws Exception {
ascOrderDTO.validation();
if (ascOrderDTO.getId() == null) {
ascOrderDTO.setCreationDate(Instant.now());
ascOrderDTO.setCreatedBy(SecurityUtils.getCurrentUserLogin().get());
//add user
ascOrderDTO.setStoreId(null);
String currentUser=SecurityUtils.getCurrentUserLogin().get();
AppUser appUser=appUserRepository.findByLogin(currentUser);
ascOrderDTO.setAppUserId(appUser.getId());
}
log.debug("Request to save AscOrder : {}", ascOrderDTO);
AscOrder ascOrder = ascOrderMapper.toEntity(ascOrderDTO);
//send notify to branch
if(!branchService.orderOk())
{
throw new BadRequestAlertException("branch not accept order", "check order with branch", "branch");
}
ascOrder = ascOrderRepository.save(ascOrder);
/*
* log.debug("start sleep"); Thread.sleep(10000); log.debug("end sleep");
*/
entityManager.setFlushMode(FlushModeType.AUTO);
entityManager.flush();
entityManager.clear();
//ascOrderRepository.flush();
try {
producerOrder.addOrder(branchId,ascOrder.getId(),true);
stateMachineHandler.stateMachine(OrderEvent.EMPTY, ascOrder.getId());
stateMachineHandler.handling(ascOrder.getId());
//return ascOrderMapper.toDto(ascOrder);
}
catch (Exception e) {
// TODO: handle exception
ascOrderRepository.delete(ascOrder);
throw new BadRequestAlertException("cannot deliver order to Branch", "try agine", "Try!");
}
}
in this code go to producer :
producerOrder.addOrder(branchId,ascOrder.getId(),true);
and this is my producer:
public void addOrder(Long branchId, Long orderId, Boolean isAccept) throws Exception {
ObjectMapper obj = new ObjectMapper();
try {
Map<String, String> map = new HashMap<>();
map.put("branchId", branchId.toString());
map.put("orderId", orderId.toString());
map.put("isAccept", isAccept.toString());
kafkaTemplate.send("orderone", obj.writeValueAsString(map));
}
catch (Exception e) {
throw new Exception(e.getMessage());
}
}
and in this code go to consumer:
kafkaTemplate.send("orderone", obj.writeValueAsString(map));
this is my consumer:
#KafkaListener(topics = "orderone", groupId = "groupId")
public void processAddOrder(String mapping) throws Exception {
try {
log.debug("i am in consumer add Order");
ObjectMapper mapper = new ObjectMapper(); Map<String, String> result = mapper.readValue(mapping,
HashMap.class);
branchService.acceptOrder(Long.parseLong(result.get("branchId")),Long.parseLong(result.get("orderId")),
Boolean.parseBoolean(result.get("isAccept")));
log.debug(result.toString());
}
catch (Exception e) {
throw new Exception(e.getMessage());
}
}
**and this code go to AcceptOrder (second method) : **
branchService.acceptOrder(Long.parseLong(result.get("branchId")),Long.parseLong(result.get("orderId")),
Boolean.parseBoolean(result.get("isAccept")));
this is my second method :
public AscOrderDTO acceptOrder(Long branchId, Long orderId, boolean acceptable) throws Exception {
ascOrderRepository.flush();
try {
if (branchId == null || orderId == null || !acceptable) {
throw new BadRequestAlertException("URl invalid query", "URL", "Check your Input");
}
if (!branchRepository.findById(branchId).isPresent() || !ascOrderRepository.findById(orderId).isPresent()) {
throw new BadRequestAlertException("cannot find branch or Order", "URL", "Check your Input");
}
/*
* if (acceptable) { ascOrder.setStatus(OrderStatus.PREPARING); } else {
* ascOrder.setStatus(OrderStatus.PENDING); }
*/
Branch branch = branchRepository.findById(branchId).get();
AscOrder ascOrder = ascOrderRepository.findById(orderId).get();
ascOrder.setDiscount(50.0);
branch.addOrders(ascOrder);
branchRepository.save(branch);
log.debug("///////////////////////////////Add order sucess////////////////////////////////////////////////");
return ascOrderMapper.toDto(ascOrder);
} catch (Exception e) {
// TODO: handle exception
throw new Exception(e.getMessage());
}
}
Adding Thread.sleep() inside saveOrder makes no sense.
processAddOrder executes on a completely different thread, with a completely different persistence context. All the while, your transaction from saveOrder might still be ongoing, with none of the changes made visible to other transactions.
Try splitting saveOrder into a transactional method and sending the notification, making sure that the transaction ends before the event handling has a chance to take place.
(Note that this approach introduces at-most-once semantics. You have been warned)

Why is spring returning me an empty llist?

I dont seem to know why Spring is returning me an empty list enough I have passed in a JSON.stringify() string from reactJS
This is my code for reactJS
postData(item){
console.log(item)
fetch("http://localhost:8080/addSuspect", {
"method": "POST",
"headers": {
"content-type": "application/json"
},
"body": item
})
.then(response => {
console.log(response);
})
.catch(err => {
console.log(err);
});
}
uploadFile(event) {
let file
let file2
//Check if the movements andsuspected case profiles are uploaded
if(event.target.files.length !== 2){
this.setState({error:true, errorMsg:"You need to upload at least 2 files!"})
return
}
//Check if the file is the correct file
console.log("Files:")
for (var i=0, l=event.target.files.length; i<l; i++) {
console.log(event.target.files[i].name);
if (event.target.files[i].name.includes("_suspected")){
file = event.target.files[i]
}
else if (event.target.files[i].name.includes("_movements")){
file2 = event.target.files[i]
}
else{
this.setState({error:true, errorMsg:"You have uploaded invalid files! Please rename the files to <filename>_suspected (For suspected cases) or <filename>_movement (For suspected case movement)"})
return
}
}
//Reads the first file (Suspected profile)
if (file) {
const reader = new FileReader();
reader.onload = () => {
// Use reader.result
const lols = Papa.parse(reader.result, {header: true, skipEmptyLines: true}, )
console.log(lols.data)
// Posting csv data into db
// this.postData('"' + JSON.stringify(lols.data) + '"')
this.postData(JSON.stringify(lols.data))
// Adds names into dropdown
this.setState({dataList: ["None", ...lols.data.map(names => names.firstName + " " + names.lastName)]})
const data = lols.data
this.setState({suspectCases: data})
}
reader.readAsText(file)
}
}
Here is what I get from console.log():
[{"id":"5","firstName":"Bernadene","lastName":"Earey","email":"bearey4#huffingtonpost.com","gender":"Female","homeLongtitude":"","homeLatitude":"","homeShortaddress":"","homePostalcode":"552209","maritalStatus":"M","phoneNumber":"92568768","company":"Yadel","companyLongtitude":"","companyLatitude":""},{"id":"14","firstName":"Mada","lastName":"Lafaye","email":"mlafayed#gravatar.com","gender":"Female","homeLongtitude":"","homeLatitude":"","homeShortaddress":"","homePostalcode":"447136","maritalStatus":"M","phoneNumber":"85769345","company":"Eare","companyLongtitude":"","companyLatitude":""}]
Below shows the Code in my Spring Controller
#RestController
public class HomeController {
private final profileMapper profileMapper;
private final suspectedMapper suspectedMapper;
public HomeController(#Autowired profileMapper profileMapper, #Autowired suspectedMapper suspectedMapper) {
this.profileMapper = profileMapper;
this.suspectedMapper = suspectedMapper;
}
#GetMapping("/listAllPeopleProfiles")
//Removes the CORS error
#CrossOrigin(origins = "http://localhost:3000")
private Iterable<Peopleprofile> getAllPeopleProfiles (){
return profileMapper.findAllPeopleProfile();
}
#GetMapping("/listAllSuspectedCases")
#CrossOrigin(origins = "http://localhost:3000")
private Iterable<Suspected> getAllSuspected(){
return suspectedMapper.findallSuspected();
}
#PostMapping("/addSuspect")
#CrossOrigin(origins = "http://localhost:3000")
private void newSuspectedcases(ArrayList<Suspected> unformattedcases){
// try {
// final JSONObject obj = new JSONObject(unformattedcases);
//
// System.out.println(obj);
//// ObjectMapper mapper = new ObjectMapper();
//// List<Suspected> value = mapper.writeValue(obj, Suspected.class);
// } catch (JSONException e) {
// e.printStackTrace();
// }
//
// Gson gson = new Gson();
// List<Suspected> suspectedCases = gson.fromJson(unformattedcases, new TypeToken<List<Suspected>>(){}.getType());
System.out.println(unformattedcases);
// for (Suspected suspected : suspectedCases){
// suspectedMapper.addSuspectedCase(suspected);
// }
}
}
I am not sure I understand your issue. This is my best guess about what you meant and what you want to happen :
You want your controller to receive ArrayList < Suspected > as the POST request body
You want your controller to return ArrayList < Suspected > as the POST response body
If that's the case, try this :
[...]
#PostMapping("/addSuspect")
#CrossOrigin(origins = "http://localhost:3000")
#ResponseBody
private ArrayList<Suspected> newSuspectedcases(#RequestBody ArrayList<Suspected> unformattedcases){
[...]
System.out.println(unformattedcases);
[...]
return unformattedcases;
}
If it's not what you meant, please provide more information.
Firstly, your controller method is returning void and not, if I undestand correctly, the payload that you're trying to send. You have to make your controller method return List<Suspected> to receive a body in the response.
Another issue is that you're missing a #RequestBody annotation on the param, which tells Spring to get the body from the request and try to deserialize it to a ArrayList of Suspects.
Another thing to note, it is a good practice to use interfaces instead of implementation classes as parameters and return value in your methods. Consider using List<Suspected> instead of ArrayList<Suspected>
So the final method should look like this:
#PostMapping("/addSuspect")
#CrossOrigin(origins = "http://localhost:3000")
private List<Suspected> newSuspectedcases(#RequestBody List<Suspected> unformattedcases){
[...]
System.out.println(unformattedcases);
[...]
return unformattedcases;
}
PS For CORS issues you may want to using a local proxy setup as described in React docs: https://create-react-app.dev/docs/proxying-api-requests-in-development/ And configure CORS for remote environments, without adding localhost:3000.

CompletableFuture for child requests

I am trying to understand CompletableFuture in Java 8. As a part of it, I am trying to make some REST calls to solidify my understanding. I am using this library to make REST calls: https://github.com/AsyncHttpClient/async-http-client.
Please note, this library returns a Response object for the GET call.
Following is what I am trying to do:
Call this URL which gives the list of users: https://jsonplaceholder.typicode.com/users
Convert the Response to List of User Objects using GSON.
Iterate over each User object in the list, get the userID and then get the list of Posts made by the user from the following URL: https://jsonplaceholder.typicode.com/posts?userId=1
Convert each post response to Post Object using GSON.
Build a Collection of UserPost objects, each of which has a User Object and a list of posts made by the user.
public class UserPosts {
private final User user;
private final List<Post> posts;
public UserPosts(User user, List<Post> posts) {
this.user = user;
this.posts = posts;
}
#Override
public String toString() {
return "user = " + this.user + " \n" + "post = " + posts+ " \n \n";
}
}
I currently have it implemented as follows:
package com.CompletableFuture;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.asynchttpclient.Response;
import com.http.HttpResponse;
import com.http.HttpUtil;
import com.model.Post;
import com.model.User;
import com.model.UserPosts;
/**
* Created by vm on 8/20/18.
*/
class UserPostResponse {
private final User user;
private final Future<Response> postResponse;
UserPostResponse(User user, Future<Response> postResponse) {
this.user = user;
this.postResponse = postResponse;
}
public User getUser() {
return user;
}
public Future<Response> getPostResponse() {
return postResponse;
}
}
public class HttpCompletableFuture extends HttpResponse {
private Function<Future<Response>, List<User>> userResponseToObject = user -> {
try {
return super.convertResponseToUser(Optional.of(user.get().getResponseBody())).get();
} catch (Exception e) {
e.printStackTrace();
return null;
}
};
private Function<Future<Response>, List<Post>> postResponseToObject = post -> {
try {
return super.convertResponseToPost(Optional.of(post.get().getResponseBody())).get();
} catch (Exception e) {
e.printStackTrace();
return null;
}
};
private Function<UserPostResponse, UserPosts> buildUserPosts = (userPostResponse) -> {
try {
return new UserPosts(userPostResponse.getUser(), postResponseToObject.apply(userPostResponse.getPostResponse()));
} catch (Exception e) {
e.printStackTrace();
return null;
}
};
private Function<User, UserPostResponse> getPostResponseForUser = user -> {
Future<Response> resp = super.getPostsForUser(user.getId());
return new UserPostResponse(user, resp);
};
public HttpCompletableFuture() {
super(HttpUtil.getInstance());
}
public List<UserPosts> getUserPosts() {
try {
CompletableFuture<List<UserPosts>> usersFuture = CompletableFuture
.supplyAsync(() -> super.getUsers())
.thenApply(userResponseToObject)
.thenApply((List<User> users)-> users.stream().map(getPostResponseForUser).collect(Collectors.toList()))
.thenApply((List<UserPostResponse> userPostResponses ) -> userPostResponses.stream().map(buildUserPosts).collect(Collectors.toList()));
List<UserPosts> users = usersFuture.get();
System.out.println(users);
return users;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
However, I am not sure if the way I am doing this is right. More specifically, in userResponseToObject and postResponseToObject Functions, I am calling the get() method on the Future, which will be blocking.
Is there a better way to implement this?
If you plan to use CompletableFuture, you should use the ListenableFuture from async-http-client library. ListenableFuture can be converted to CompletableFuture.
The advantage of using CompletableFuture is that you can write logic that deals with Response object without having to know anything about futures or threads. Suppose you wrote the following 4 methods. 2 to make requests and 2 to parse responses:
ListenableFuture<Response> requestUsers() {
}
ListenableFuture<Response> requestPosts(User u) {
}
List<User> parseUsers(Response r) {
}
List<UserPost> parseUserPosts(Response r, User u) {
}
Now we can write a non-blocking method that retrieves posts for a given user:
CompletableFuture<List<UserPost>> userPosts(User u) {
return requestPosts(u)
.toCompletableFuture()
.thenApply(r -> parseUserPosts(r, u));
}
and a blocking method to read all posts for all users:
List<UserPost> getAllPosts() {
// issue all requests
List<CompletableFuture<List<UserPost>>> postFutures = requestUsers()
.toCompletableFuture()
.thenApply(userRequest -> parseUsers(userRequest)
.stream()
.map(this::userPosts)
.collect(toList())
).join();
// collect the results
return postFutures.stream()
.map(CompletableFuture::join)
.flatMap(List::stream)
.collect(toList());
}
Depending on the policy you want to use to manage blocking response, you can explore at least these implementations:
1) Invoking the overloaded method get of the class CompletableFuture with a timeout:
List<UserPosts> users = usersFuture.get(long timeout, TimeUnit unit);
From the documentation:
Waits if necessary for at most the given time for this future to
complete, and then returns its result, if available.
2) Using the alternative method getNow:
List users = usersFuture.getNow(T valueIfAbsent);
Returns the result value (or throws any encountered exception) if
completed, else returns the given valueIfAbsent.
3) Using CompletableFuture instead of Future, you can force manually the unlocking of get calling complete :
usersFuture.complete("Manual CompletableFuture's Result")

DynamoDB - how to get Primary Key (which is random id) from database to make endpoind class?

I've made method that I use to edit Item from database.
This is how my method looks:
public Product editProduct(PrimaryKey primaryKey, Product content) {
UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey(primaryKey).withValueMap(createValueMap(content));
UpdateItemOutcome itemOutcome = databaseController.getTable(PRODUCT_TABLE).updateItem(updateItemSpec);
return convertToProduct(itemOutcome);
}
private Map<String, Object> createValueMap(Product content) {
Map<String, Object> result = new HashMap<>();
result.put("name", content.getName());
result.put("calories", content.getCalories());
result.put("fat", content.getFat());
result.put("carbo", content.getCarbo());
result.put("protein", content.getProtein());
result.put("productKinds", content.getProductKinds());
result.put("author", content.getAuthor());
result.put("media", content.getMedia());
result.put("approved", content.getApproved());
return result;
}
private Product convertToProduct(UpdateItemOutcome itemOutcome) {
Product product = new Product();
product.setName(itemOutcome.getItem().get("name").toString());
product.setCalories(itemOutcome.getItem().getInt("calories"));
product.setFat(itemOutcome.getItem().getDouble("fat"));
product.setCarbo(itemOutcome.getItem().getDouble("carbo"));
product.setProtein(itemOutcome.getItem().getDouble("protein"));
product.setProductKinds(itemOutcome.getItem().getList("productKinds"));
ObjectMapper objectMapper = new ObjectMapper();
try {
Author productAuthor = objectMapper.readValue(itemOutcome.getItem().getString("author"), Author.class);
product.setAuthor(productAuthor);
} catch (IOException e) {
e.printStackTrace();
}
try {
Media productMedia = objectMapper.readValue(itemOutcome.getItem().getString("media"), Media.class);
product.setMedia(productMedia);
} catch (IOException e) {
e.printStackTrace();
}
return product;
}
Now I want to create endpoint class for this method but I have problem, I need to get primarykey as parameter (it's looks like this for example: 2567763a-d21e-4146-8d61-9d52c2561fc0) and I don't know how to do this.
At the moment my class looks like that:
public class EditProductLambda implements RequestHandler<Map<String, Object>, ApiGatewayResponse> {
private LambdaLogger logger;
#Override
public ApiGatewayResponse handleRequest(Map<String, Object> input, Context context) {
logger = context.getLogger();
logger.log(input.toString());
try{
Product product = RequestUtil.parseRequest(input, Product.class);
//PrimaryKey primaryKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
KitchenService kitchenService = new KitchenService(new DatabaseController(context, Regions.EU_CENTRAL_1), logger);
Product editedProduct = kitchenService.editProduct(primaryKey, product);
return ResponseUtil.generateResponse(HttpStatus.SC_CREATED, editedProduct);
} catch (IllegalArgumentException e){
return ResponseUtil.generateResponse(HttpStatus.SC_BAD_REQUEST, e.getMessage());
}
}
Can someone give me some advice how to do that? Or maybe my method is done wrong?
So first you have to create a trigger to Lambda function and ideal prefer here would be an API gateway. You can pass your data as query string or as a request body to API gateway.
You can use body mapping template in the integration request section of API gateway and get request body/query string. Construct a new json at body mapping template, which will have data from request body/query string. As we are adding body mapping template your business logic will get the json we have constructed at body mapping template.
Inside body mapping template to get query string please do ,
$input.params('querystringkey')
For example inside body mapping template (If using query string),
#set($inputRoot = $input.path('$'))
{
"primaryKey" : "$input.params('$.primaryKey')"
}
if passing data as body then,
#set($inputRoot = $input.path('$'))
{
"primaryKey" : "$input.path('$.primaryKey')"
}
Please read https://aws.amazon.com/blogs/compute/tag/mapping-templates/ for more details on body mapping template

Categories