Send List from Angular to Spring - javascript

Iam trying to send an Object from angular to my spring to add a new product. The product has a list of prices and sizes. This is how it looks like in backend:
#Setter
#Getter
public class ProductDto {
private Long id;
private Long secondId;
private String name;
private String description;
private MultipartFile img;
private byte[] returnedImg;
private Long categoryId;
private String categoryName;
private Long restaurantId;
private Long userId;
private List<SizePriceDto> sizePrices;
}
Controller class:
#PostMapping("product/{categoryId}/{restaurantId}/{userId}")
public GeneralResponse addProduct(#PathVariable Long categoryId, #PathVariable Long restaurantId, #PathVariable Long userId, #ModelAttribute ProductDto productDto) {
GeneralResponse response = new GeneralResponse();
try {
return restaurantService.addProduct(categoryId, restaurantId, userId, productDto);
} catch (Exception ex) {
response.setStatus(HttpStatus.BAD_REQUEST);
response.setMessage("Sorry Something Wrong Happened.");
return response;
}
}
Frontend:
this.sizes.controls.forEach((sizeGroup, index) => {
sizesAndPrices.push({
size: sizeGroup.get('size').value,
price: sizeGroup.get('price').value
});
});
formData.append('sizePrices', '[{"size":"30","price":343},{"size":"frefgv","price":343}]');
And this is the error that i get when i submit the form in angular:
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors<EOL>Field error in object 'productDto' on field 'sizePrices': rejected value [[{"size":"34","price":2342},{"size":"f4ef","price":3434}]]; codes [typeMismatch.productDto.sizePrices,typeMismatch.sizePrices,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [productDto.sizePrices,sizePrices]; arguments []; default message [sizePrices]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.List' for property 'sizePrices'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.restaurant.dto.SizePriceDto' for property 'sizePrices[0]': no matching editors or conversion strategy found]]
SizePriceDto Class
#Getter
#Setter
public class SizePriceDto {
private String size;
private Long price;
}
SizePrice Class:
#Entity
#Getter
#Setter
public class SizePrice {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String size;
private Long price;
#ManyToOne
#JoinColumn(name = "product_id")
private Product product;
}
My request from angular:
https://i.postimg.cc/zfnXT4mT/image.png
I tried alot of methods but nothing works and i dont have any idea how to fix this error.

Related

Retrofit + GSON = entering "onFailure"

I am trying to first use the Retrofit to get data to an course. But I figured out that my program is going to the "onFailure" option.
ERROR MESSAGE:
2020-03-07 18:54:04.499 17756-17756/com.example.apirequest I/MainActivity: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
Basically I'm trying to get firstly only the "launch_year" from API https://api.spacexdata.com/v3/launches/
Can someone help me to figure out the reason I can't get it right?
In grade I added:
implementation 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
My codes are bellow:
MainActivity:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Retrofit retrofit = new Retrofit.Builder().
baseUrl(APIService.urlBase)
.addConverterFactory(GsonConverterFactory.create()).
build();
APIService service = retrofit.create(APIService.class);
Call<rocketCatalog> requestModels = service.listCaralog();
requestModels.enqueue(new Callback<rocketCatalog>() {
#Override
public void onResponse(Call<rocketCatalog> call, Response<rocketCatalog> response) {
rocketCatalog catalog = response.body();
for (Rockets rocket : catalog.rocket){
Log.i(TAG,String.format("%s",rocket.getLaunch_date()));
}
}
#Override
public void onFailure(Call<rocketCatalog> call, Throwable t) {
Log.i(TAG,String.format("============= Failure =============="));
}
});
LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
}
}
APIService:
public interface APIService {
public static final String urlBase = "https://api.spacexdata.com/v3/";
#GET("launches")
Call<rocketCatalog> listCaralog();
}
rocketCatalog:
public class rocketCatalog {
public List<Rockets> rocket;
public List<Rockets> getRocket() {
return rocket;
}
public void setRocket(List<Rockets> rocket) {
this.rocket = rocket;
}
}
Rockets:
public class Rockets {
String launch_date;
public String getLaunch_date() {
return launch_date;
}
public void setLaunch_date(String launch_date) {
this.launch_date = launch_date;
}
}
Your endpoint returns a List so you need a List type for your response.
public static final String urlBase = "https://api.spacexdata.com/v3/";
#GET("launches")
Call<List<Rockets>> listCaralog();
also make sure the field launch_date in your Rockets Class exists in the response.
with your help I figured it out what was happening.
Indeed I was receiving a List, but I had to re struct, I've made what Mohamed Mohsin suggested and modified my rocketCatalog.java to:
rocketCatalog:
String launch_year;
public String getLaunch_year() {
return launch_year;
}
public void setLaunch_year(String launch_date) {
this.launch_year = launch_date;
}
}
Also, I changed "launch_date" which was wrong to "launch_year"
Thank you so much, again!

Angular 7 Service Returns Undefined from restful API

I'm trying to return a list of tasks from and Angular service that gets the data from a restful .NET API. The API returns the proper data, but when console.log the result from the subscribed to function it is only undefined. Please help!
Here is the API method that is functioning correctly:
TaskController.cs
[HttpGet, Route("")]
public IEnumerable<GetAllTasksAndInfoDto> GetAll()
{
IEnumerable<GetAllTasksAndInfoDto> tasks = _taskRepository.GetAllTasksAndInfo();
return tasks;
}
I have two services on called task.service.ts and one called email-notification.service.ts. Task is to return all the tasks in a collection. Email-Notification is to retrieve the tasks from the task service, then iterate through them to check a for a specific property value in the task data.
Here is the method from task.service.ts:
export class TaskService {
constructor(private http: HttpClient, private messageService: MessageService) {}
getTasks(): Observable<getAllTasksAndInfo[]> {
return this.http.get<getAllTasksAndInfo[]>(http://localhost:xxxxx/api/task)
.pipe(
tap(_=>this.log('fetched tasks')),
catchError(this.handleError<getAllTasksAndInfo[]>('getTasks', [])));
}
I'm not sure how to check the data at this ^ point, but it's not showing an error.
Here is the code from email-notification that is returning "Undefined":
export class EmailNotificationService{
tasks: getAllTasksAndInfo[];
constructor(private http: HttpClient, private messageService: MessageService, public taskService: TaskService)
{
this.getTasks().subscribe(result => this.tasks = result);
}
getTasks(): Observable<getAllTasksAndInfo[]>{
return this.taskService.getTasks();
}
this.tasks.forEach((task) => {
console.log(`task: ${JSON.stringify(task)}`);
}
});
Here I am getting an error in the console for trying to iterate through and undefined object.
Here is my typescript class:
export class getAllTasksAndInfo {
taskId: number;
stepName: string;
officeName: string;
csrName: string;
taskType: string;
daysActive: number;
}
and here is my API class:
public class GetAllTasksAndInfoDto
{
public int taskId { get; set; }
public string stepName { get; set; }
public string officeName { get; set; }
public string csrName { get; set; }
public string taskType { get; set; }
public int daysActive { get; set; }
}
Any help appreciated. Thank you!
It might be because you have not subscribed to the Observable or the initial data that is the tasks array is preset to undefined
have you tried using rxjs to subscribe to your observable in your EmailNotificationService sometimes it might come in undefined because the initial value of the array is undefined to begin with maybe setting it up with an empty array might help
private tasks: getAllTasksAndInfo[] = [];
constructor(private http: HttpClient, private messageService: MessageService, public taskService: TaskService)
{
this.tasks = this.getTasks();
}
getTasks() {
this.taskService.getTasks().subscribe((tasks: getAllTasksAndInfo[]) => {
console.log(tasks);
return tasks;
});
}

Getting nested exception is com.fasterxml.jackson.databind.JsonMappingException when converting json in java object in angulajs

Whenever I'm sending JSON from client to server and it tries to convert this JSON into java object. It is giving following exception
Failed to read HTTP message:
org.springframework.http.converter.HttpMessageNotReadableException:
Could not read document: N/A\n at [Source:
java.io.PushbackInputStream#18f89001; line: 1, column: 1102] (through
reference chain:
Request["fields"]->java.util.ArrayList[0]->Field["value"]); nested
exception is com.fasterxml.jackson.databind.JsonMappingException
My java code:
public class Field implements Serializable {
private String name;
private String value;
public Field(){
}
public Field(String name, String value ) {
this.name = name;
this.value = value;
}
public String getName(){
return name;
}
public String getValue(){
return value;
}
public void setValue(String newValue) throws Exception {
someValidation();//Some validation on value
value = newValue;
}
public void setName(String name) {
this.name = name;
}
}
public class Request implements Serializable{
private String name;
private List<Field> fields;
public Request() {
}
public String getName() {
return viewName;
}
public void setName(String name) {
this.name = name;
}
public List<Field> getFields() {
return fields;
}
public void setField(List<Field> fields) {
this.fields = fields;
}
}
My JSON is :
{
"name" : "name0",
"fields" : [{"name":"abc0", "value":"0"}, {"name":"def0", "value":"0"}]
}
Your code looks fine, I think the problem might be with your request header, which can confuse the server.
I suggest you try to post a simpler JSON to your server, maybe just a string and find out step by step where is your failure point, check your request and maybe simulate one with POSTMAN or something familiar to make sure the client isn't the problem here.

How to set up retrofit for my application?

I am just learning about Retrofit and Android development. What I would like to do is send a fairly complex JSON object to a server from a website and be able to retrieve it using Retrofit as a Java Object for my Android Application.
So basically something like this,
Website JSON --Ajax Call--> Server --Retrofit--> Android Application (Java Object / Collection)
Which server would be the best to set this up? Also are there any good references on how to accomplish this?
Thank you
With retrofit and android, you only need a couple of things
A java model
public class User {
private String name;
private String password;
public User(String name, String password) {
this.name = name;
this.password = password;
}
//Getters and setters
//...
}
A retrofit interface
public interface APIService {
#FormUrlEncoded
#Headers("Accept: application/json")
#POST("register")
Call<AuthRegister> createUser(
#Field("name") String name,
#Field("password") String password
);
}
A callback for retrofit
public class AuthRegister {
#SerializedName("message")
#Expose
private String message;
#SerializedName("errors")
#Expose
private Errors errors;
public String getMessage() {
return message;
}
public Errors getErrors() {
return errors;
}
}
A network client
public class NetworkClient {
public static Retrofit retrofit;
/*
This public static method will return Retrofit client
anywhere in the appplication
*/
public static Retrofit getRetrofitClient() {
//If condition to ensure we don't create multiple retrofit instances in a single application
if (retrofit == null) {
//Defining the Retrofit using Builder
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.level(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
// .addInterceptor(interceptor)
.connectTimeout(30, TimeUnit.MINUTES)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(Config.BASE_URL) //This is the only mandatory call on Builder object.
.client(client)
.addConverterFactory(GsonConverterFactory.create()) // Convertor library used to convert response into POJO
.build();
}
return retrofit;
}
}
The call inside the activity you are to display the response or save the data
private void saveUser(String name, String password){
Retrofit retrofit = NetworkClient.getRetrofitClient();
APIService service = retrofit.create(APIService.class);
Call<AuthRegister> call = service.createUser(name, password);
call.enqueue(new Callback<AuthRegister>() {
#Override
public void onResponse(Call<AuthRegister> call, Response<AuthLogin> response) {
if (response.code() == 200) {
if (response.body().getMessage() != null) {
Toast.makeText(mContext, "Success", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mContext, "Could not save user", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(mContext, "Could not save user", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<AuthRegister> call, Throwable t) {
new PrefManager(mContext).clearUser();
Log.e(TAG, t.toString());
Toast.makeText(mContext, "Could not save user", Toast.LENGTH_SHORT).show();
}
});
}
You can use any server as you need. Any complex JSON can be handled by retrofit library. Check the Following link Retrofit android example web services

Why are some of my values not getting populated by webapi

I'm working on a web-api controller. I built a DTO to hold a Note.
public class NoteContainer
{
public long? NoteId { get; set; }
public string Type { get; set; }
public string NoteText { get; set; }
public NoteContainer(Note note, string type = null)
{
NoteId = note.Id;
NoteText = note.NoteText;
Type = type;
}
}
I have a method in my controller:
[HttpPost]
public void EditNote(NoteContainer container)
{
//do work here
}
Before the NoteContainer is sent from the client it has all values. When it gets to the server, type is null! Should I not use a variable named type? Why am I losing the value?
Using Postman I'm sending this json:
{
"noteId": 10,
"type": "person",
"noteText": "loves broccoli",
}
That needs default constructor I believe. The problem can be that the Note class gets instantiated first and is given to NoteContainer.

Categories