Post object inside another object to mongoDB via Spring rest api - java

I'm creating a basic crud application for members in a library. I've created a spring api to get the values and insert it into the DB. So when I check it using postman a error is shown. (500: Internal server error)Below diagram shows a request i tried to sent.
As shown above I'm sending another object inside the Member object and once I removed the latestBook, there is no error the value is posted.
I want to resolve this issue, please help me with this.
API
#PostMapping("/m")
public Member save(#RequestBody Member member){
repository.save(member);
return member;
}
Member.java
#Document(collection = "Members")
public class Member {
#Id
private String id;
private String name;
private Book latestBook;
private String gender;
private int contact;
public Member() {
}
public Member(String id, String name, Book latestBook, String gender, int contact) {
this.id= id;
this.name = name;
this.startMembershipDate = startMembershipDate;
this.gender = gender;
this.contactNum = contactNum;
}
//getters , setters and toString method
}
Book.java
public class Book{
private String name;
private String author;
private int year;
public Book(String name, String author, int year) {
this.name= name;
this.author= author;
this.year = year;
}
//getters , setters and toString method
}
I think the problem is with the Book class so please help me to solve this issue.
Not only for posting it does not work for delete either.

Solved the issue.
#Document(collection = "Members")
public class Member {
#Id
private String id;
private String name;
private Book latestBook = new Book();
private String gender;
private int contact;
public Member() {
}
public Member(String id, String name, Book latestBook, String gender, int contact) {
this.id= id;
this.name = name;
this.startMembershipDate = startMembershipDate;
this.gender = gender;
this.contactNum = contactNum;
}
//getters , setters and toString method
}
////////////////////////
public class Book{
private String name;
private String author;
private int year;
Book(){}
public Book(String name, String author, int year) {
this.name= name;
this.author= author;
this.year = year;
}
//getters , setters and toString method
}

Related

is convertion to DTO like this ok or it is a bad practice?

I have Entity that has list of another entities inside. Same for DTO, dto object with a list of another dto.
I need to convert Entity to DTO with the list inside.
Here how it looks with streams ( a bit messy, don't know if it is ok to use ):
public List<RestaurantDto> getAll() {
List<Restaurant> restaurantList = restaurantRepository.findAll();
return restaurantList.stream()
.map(restaurant -> new RestaurantDto(restaurant.getName(), restaurant.getAddress(),
restaurant.getDishes().stream()
.map(dish -> new DishDto(dish.getId(), dish.getName(), dish.getPrice(), dish.getRestaurant()))
.collect(Collectors.toList())))
.collect(Collectors.toList());
}
Here is my DTO
#Getter
#Setter
#NoArgsConstructor
public class RestaurantDto {
private String name;
private String address;
private List<DishDto> dishes;
private int votes;
public RestaurantDto(String name, String address) {
this.name = name;
this.address = address;
}
public RestaurantDto(String name, String address, List<DishDto> dishes) {
this.name = name;
this.address = address;
this.dishes = dishes;
}
public void addDish(DishDto dishDto) {
dishes.add(dishDto);
}
public List getDeishes() {
return Collections.unmodifiableList(dishes);
}
}
And DTO that is in List
#Getter
#Setter
#NoArgsConstructor
#ToString
public class DishDto {
private int id;
#NotBlank
private String name;
#Digits(integer = 12, fraction = 2)
private double price;
private String restaurantName;
private String restaurantAddress;
#Digits(integer = 12, fraction = 0)
private int restaurantId;
public DishDto(int id, String name, double price, int restaurantId) {
this.id = id;
this.name = name;
this.price = price;
this.restaurantId = restaurantId;
}
public DishDto(int id, String name, double price, Restaurant restaurant) {
this.id = id;
this.name = name;
this.price = price;
this.restaurantName = restaurant.getName();
this.restaurantAddress = restaurant.getAddress();
this.restaurantId = restaurant.getId();
}
}
I do appreciate your help a lot!
In my opinion, retrieving the whole entity and then converting it to DTOs in order to have fewer fields can be considered as an anti-pattern.
You should use projections if you want to retrieve less fields from the entity.
Bringing all the fields to the memory and then using just couple of them is not a good idea.
Take a look at projections. The following resources may help:
https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections

How do I go about creating the method?

I'm currently trying to create a class in java, to this specification:
I'm not sure how to create "ratings" since I'm seeing its using some
map function using the input of a string and an integer.
Here's my code so far:
public class Movie {
String ID;
String Name;
String Description;
String Genre[];
String Directors[];
String Actors[];
String Language;
String CountryOfOrigin;
}
Please create different objects for genre, director, actor and rating. It will be a best practice when you try to add more information to each entity.
Use access modifier "private" to each attribute and implement get,set methods as required.
Use ArrayLists instead of arrays to avoid resizing efforts when required.
import java.util.ArrayList;
import java.util.List;
public class Genre {
private int id;
private String name;
public Genre(int id, String name) {
this.id = id;
this.name = name;
}
}
public class Director {
private int id;
private String name;
public Director(int id, String name) {
this.id = id;
this.name = name;
}
}
public class Actor {
private int id;
private String name;
public Actor(int id, String name) {
this.id = id;
this.name = name;
}
}
public class Rating {
private int value;
private String name;
public Actor(int value, String name) {
this.value = value;
this.name = name;
}
}
public class Movie {
private int id;
private String name;
private String description;
private List<Genre> generes;
private List<Director> directors;
private List<Actor> actors;
private String language;
private String countryOfOrigin;
pulic Movie(int id, String name, String description, String language, String countryOfOrigin){
this.id = id;
// set other variables
this.actors = new ArrayList<Actor>();
// create other lists
}
public void addGenere(Genre genere){
this.generes.add(genere);
}
// implement other add methods to lists
}

Spring MVC model binding not working for non public members

I have class Product with members like Name, Description... which are private, and I have public getter and setter methods. I tried to make Spring Boot MVC REST controller with POST method but it seams that what I am sending is not bind to model. This is JSON I'm sending to controller:
{
"Name": "proizvod7",
"Description": "neki opis2",
"CategoryId":1,
"Price":"15"
}
This is my code:
#RequestMapping(value = {"","/"},method = RequestMethod.POST,consumes = "application/json",produces="application/json")
public ResponseEntity PostProduct(#RequestBody #Valid Product p, BindingResult result){
if (!result.hasErrors()) {
return new ResponseEntity<>(service.insert(p), HttpStatus.CREATED);
} else
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
}
I figured that out when I created new class ProductDto which has public members Name, Description...
This is working version:
#RequestMapping(value = {"","/"},method = RequestMethod.POST,consumes = "application/json",produces="application/json")
public ResponseEntity PostProduct(#RequestBody #Valid ProductDto productDto, BindingResult result) {
if (!result.hasErrors()) {
Product p = new Product(productDto.Name, productDto.Price, productDto.Description, productDto.CategoryId);
return new ResponseEntity<>(service.insert(p), HttpStatus.CREATED);
} else {
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
}
However project is simple enough so I don't want to introduce DTO classes, but I would like to have private members inside my initial Product class with public getters and setters. Is it possible?
EDIT:
Here is Product class:
#Data
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "products")
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
public Product(#NotNull String name, BigDecimal price, String description, Long category_id) {
Name = name;
Price = price;
Description = description;
Category_id = category_id;
}
public Long getId() {
return Id;
}
public void setId(Long id) {
Id = id;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public BigDecimal getPrice() {
return Price;
}
public void setPrice(BigDecimal price) {
Price = price;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
#NotNull
private String Name;
private BigDecimal Price;
private String Description;
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public Long getCategory_id() {
return Category_id;
}
public void setCategory_id(Long category_id) {
Category_id = category_id;
}
#Column(name = "category_id",nullable = true)
private Long Category_id;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name="category_id",updatable = false,insertable = false)
private Category category;
}
It seems your field names are breaking the deserializing logic. I do not know why are you trying to use those uppercase field names, but the problem is that when there is a setter for Name field, setName(), Jackson thinks this maps to a field name, not Name, hence the issue.
You should use #JsonProperty()
#JsonProperty("Name")
private String Name;
#JsonProperty("Price")
private BigDecimal Price;
#JsonProperty("Description")
private String Description;
#JsonProperty("categoryId")
#Column(name = "category_id", nullable = true)
private Long Category_id;
Also with #Data annotation from Lombok, you do not need to write all those getters/setters, they are already generated for you.
You can use #JsonSetter at the public setters... something like this
public class MyBean {
private String name;
#JsonSetter("name")
public void setTheName(String name) {
this.name = name;
}
}
You can check more examples here:
https://www.baeldung.com/jackson-annotations
#JsonSetter ref here https://fasterxml.github.io/jackson-annotations/javadoc/2.0.0/com/fasterxml/jackson/annotation/JsonSetter.html

Fetch data based on user id from MYSQL and display in recyclerview in android studio

So I have a database that contains 2 tables, one for user activities named tblactivity and the other named tblusers:
tblactivity contains multiple data for a user and I want to display entries in tblactivity in a recyclerview based on the logged-in user whose data I fetched from tblusers. tblactivity has userid column and I would like to know how to go about this.
EDIT: More Details:
So am using slim framework: DbConnect.php
//Method to get emails of a particular user
public function getActivity(){
$stmt = $this->con->prepare("SELECT id, userid, subject, message FROM tblactivity");
$stmt->execute();
$stmt->bind_result($id, $userid, $subject, $message);
$users = array();
while($stmt->fetch()){
$user = array();
$user['id'] = $id;
$user['userid'] = $userid;
$user['subject'] = $subject;
$user['message'] = $message;
array_push($users, $user);
}
return $users;
}
My index.php code
$app->get('/allactivity', function(Request $request, Response $response){
$db = new DbOperations;
$users = $db->getActivity();
$response_data = array();
$response_data['error'] = false;
$response_data['users'] = $users;
$response->write(json_encode($response_data));
return $response
->withHeader('Content-type', 'application/json')
->withStatus(200);
});
Now in android studio:
My Activity.java model:
public class Activity {
private int id;
private int userid;
private String subject;
private String message;
private String to;
public Activity(String subject, String message) {
this.id = id;
this.userid = userid;
this.subject = subject;
this.message = message;
this.to = to;
}
public int getId() {
return id;
}
public int getUserid() { return userid; }
public String getSubject() { return subject; }
public String getMessage() {
return message;
}
public String getTo() { return to; }
}
User.java Model
public class User {
private int id;
private String email;
private String firstname;
private String lastname;
private String companyname;
private String postcode;
private String city;
private String state;
private String phonenumber;
private String address1;
private String country;
private String status;
private int currency;
private String credit;
private String language;
private int email_verified;
public User(int id, String email, String firstname, String lastname, String companyname, String address1, String city,
String state, String postcode, String country, String phonenumber, String status, int currency, String credit,
String language, int email_verified) {
this.id = id;
this.email = email;
this.firstname = firstname;
this.lastname = lastname;
this.companyname = companyname;
this.address1 = address1;
this.city = city;
this.state = state;
this.postcode = postcode;
this.country = country;
this.phonenumber = phonenumber;
this.status = status;
this.currency = currency;
this.credit = credit;
this.language = language;
this.email_verified = email_verified;
}
public int getId() {
return id;
}
public String getEmail() {
return email;
}
public String getFirstName() {
return firstname;
}
public String getLastName() {
return lastname;
}
public String getCompanyName() { return companyname; }
public String getAddress1() {
return address1;
}
public String getCity() {
return city;
}
public String getState() { return state; }
public String getPostcode() {
return postcode;
}
public String getCountry() {
return country;
}
public String getPhonenumber() {
return phonenumber;
}
public String getStatus() { return status; }
public int getCurrency() { return currency; }
public String getCredit() {
return credit;
}
public String getLanguage() {
return language;
}
public int getEmail_verified() { return email_verified; }
}
I am using Retrofit client to get the json output from php.
#GET("allactivity")
Call<List<Activity>> getActivityData();
}
If I understood you correctly your question goes about data handling. Now there are two possibilities, if you have a local database on the device, then you will have to create a SQLLiteOpenHelper and pass in a SQL Query, in which you clarify what data you need an example could be:
SELECT * FROM tblactivity WHERE userid = 30;
In this case you would get all the info about the user with the id 30. Now if you have an online database, you have to write a php file, which allows you the communication with the sql database, if I add this here as well, it would go too far. Here is tutorial you could check out about that: https://www.w3schools.com/php/php_mysql_connect.asp
As soon as you have uploaded the php file via an ftp handler, you need to open an internet connection with a link like this: www.mydomain.com/database.php?userid=30 .
You pass in a restriction of which users you are in interested in. In your php file you can then get the data with:
$sql = "SELECT * FROM tblactivity WHERE userid = ".$_GET["userid"];
Then you need to read the incoming data and parse it. My choice is to use json_encode in your php file and to store the incoming data in the app as JSON. You will need to inform yourself about that as well, but it's not all too difficult.
If you have received the data, you need to create a custom object, where you store all the necessary information:
public class User {
public User(String name, int _id, String email){
//save the information in local variables
}
public String getName(){
return mName;
}
//Add more methods to get and set the different variables.
}
Then the next thing you have to do is create a custom Adapter to populate the items of the RecyclerView. But again, this would be too much to explain here. Here would be the link to another tutorial: https://medium.com/mindorks/custom-array-adapters-made-easy-b6c4930560dd
It may seem like a lot now, but I have also just started with this, and you'll get the hang of it fast.

java creating an object in subclass

Having trouble creating an author object in the Book class.This is indeed Homework, I have came up with all the methods on my own and have been staring at this assignment for 2 hours now. any tips hints will be appreciated. I believe I am only allowed this one Author constructor with 3 parameters otherwise I would just have made an Author constructor with no arguments and the problem would be gone.
public class Author {
protected String name;
protected String email;
protected char gender;
public Author(String name, String email, char gender)
{
this.name = name;
this.email = email;
this.gender = gender;
}
public String getName()
{
return name;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
public char getGener()
{
return gender;
}
public String toString()
{
return ( name + "(" + gender + ")#" + email);
}
}
public class Book extends Author{
private String name;
private Author author;
private double price;
private int qtyInStock = 0;
public Book(String name, Author author,Double price)
{
this.author = new author;
this.name = name;
this.price = price;
}
public Book(String name, Author author, double price, int qtyInStock)
{
this.name = name;
this.author = author;
this.price = price;
this.qtyInStock = qtyInStock;
}
public String getName()
{
return name;
}
public Author getAuthor()
{
return author;
}
public double getPrice()
{
return price;
}
public void setPrice(double price)
{
this.price = price;
}
public int getQtyInStock()
{
return qtyInStock;
}
public void setQtyInStock(int qtyInStock)
{
this.qtyInStock = qtyInStock;
}
public String toString()
{
return (name + " by " + author + "(" + super.gender + ")at" + super.email);
}
}
It should be this.author = author; without the new keyword.
You are assigning the Author object in the constructor, not creating new one.
By the way, Book inherits from Author which means it already has the Author functionality. You don't have to save it as member.
Seems strange that Book extends Author. A Book is not an Author.
I think what you want to do is create a Book object that has an Author, but you are already passing in an Author to your Book constructor, so what is the problem?
class Book {
public Book(String title, Author author) {
this.title = title;
this.author = author;
}
}
If you're wondering how to create the Author, just create it before you pass it to the Book.
Author author = new Author("bob", "bob#email.com", 'm');
Book book = new Book("some title", author);
Does that make sense?
You are inheriting Author in Book, inheritance is is a relationship, means Book is a Author which is not true in real world scenario , you need has a relation which makes sense , that Book has a Author.
So don't extend author in Book , keep a field of author in it as you have already did. Change you design.
There are multiple mistakes in your code:
as #Guy said, you need to assign the author with this.author = author, without the new keyword.
you are shadowing the name variable from the Author class by also including a variable with the same name in the Book class. Remove that variable and the getter and setter methods from the Book class.
You donĀ“t have a no parameter constructor, so you have to call the parent constructor in your Book class by calling super(name, email, gender);.
you should replace new author with author, also when you call the constructor of a sub Type, the Parent class's default constructor is invoked by default. so you need to specify a default constructor in your parent class, or to prevent this explicitly call your parametric constructor of parent class in the child class constructor .
Besides changing tothis.author = author.
You also need to add super(name, name, 'M'); to the two constructors of the Book class.
public class Book extends Author{
private String name;
//private final String email;
// private char gender;
private Author author;// = new Author(name,super.email,super.gender);
private double price;
private int qtyInStock = 0;
public Book(String name, Author author,double price)
{
//super();
this.author = author;// new Author(name,super.email,super.gender);
super.name = author.getName();
super.gender = author.getGender();
super.email = author.getEmail();
this.name = name;
this.price = price;
}
public Book(String name, Author author, double price, int qtyInStock)
{
this.author = author;
super.name = author.getName();
super.gender = author.getGender();
super.email = author.getEmail();
this.name = name;
this.price = price;
this.qtyInStock = qtyInStock;
}
public String getName()
{
return name;
}
public Author getAuthor()
{
return author;
}
public double getPrice()
{
return price;
}
public void setPrice(double price)
{
this.price = price;
}
public int getQtyInStock()
{
return qtyInStock;
}
public void setQtyInStock(int qtyInStock)
{
this.qtyInStock = qtyInStock;
}
public String toString()
{
return (super.name + " by " + this.name + "(" + super.gender + ")at" + super.email);
}
also added this to the author class
public Author()
{
}

Categories