JAVA Spring boot how to post arraylist in Postman - json

I am trying to save some books via request but I am getting errors. How do I exactly do this? This is the model
#Entity
public class Reservation {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String user;
private int period;
#OneToMany
private List<Books> books;
public static String error () {
return "Input error";
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public int getPeriod() { return period;}
public void setPeriod(int period) {this.period = period;}
public List<Books> getBooks() { return books;}
public int getId() {return id;}
public void setId(int id) {this.id = id;}
#Entity
public class Books implements Serializable {
#Id
#GeneratedValue( strategy = GenerationType.IDENTITY )
private int id;
private String name;
}
}
Controller:
#PostMapping("/reserveBook")
public String reserveBook(#RequestBody Reservation reservation)
{
if (reservation.getPeriod() > 2)
return Book.error();
else{
reserveRepo.save(reservation);
return "success";
}
}
Tried json like this
{
"user": "Jason",
"books":[{"name": "Wonders"}, {"name": "Good classics"}],
"period": 2
}

What exact error you are getting? Can you try to make your inner class static? Like
public static class Books implements Serializable

Related

Spring Boot: How to retrieve the username by user_id?

I have already connected my springboot to MySQL database. I want to display the username when user_id is specified in the HTTP request. e.g. http://8080/user/1 must display the name of the user with user_id 1.
The table contains attributes as:
| Integer user_id; | String username; | String fathername; | String mothername;
I have already tried this code in by Controller class but i does not seem to be working
#RequestMapping("/{userid}")
#ResponseBody
public String getById(Integer userid) {
String name="";
try {
Optional<Persondetails> persondetails=persondetailsRepository.findById(personid);
name = String.valueOf(userdetails.getName());
}
catch (Exception ex) {
return "Name not found";
}
return "The Name of the user is : " + name;
}
my repository code:
import java.util.List;
import java.util.Optional;
public interface UserdetailsRepository extends JpaRepository<Userdetails, Integer> {
public Optional<Userdetails> findById(Integer userid);
}
It says getName() is undefined for the type Optional
But i have defined it in Userdetails class
public class Userdetails {
#Id
#GeneratedValue
#Column(name="user_id")
private Integer userid;
#Column(name="name")
private String name;
#Column (name="fathers_name")
private String fathersname;
#Column(name="mothers_name")
private String mothersname;
public Userdetails() {
}
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getName() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String getFathersname() {
return fathersname;
}
public void setFathersname(String fathersname) {
this.fathersname = fathersname;
}
public void setMothersname(String mothersname) {
this.mothersname = mothersname;
}
public String getMothersname() {
return mothersname;
}
}
It's missing the method type GET, you can do by two options:
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public User findOne(#PathVariable("id") int id){
return userService.findById(id);
}
OR
#GetMapping("/{id}")
public String getString(#PathVariable("id") int id) {
return "Helloworld";
}
Spring boot Connect with Mysql and get Data.
application.properties
server.contextPath=/demo-user
spring.datasource.url=jdbc:mysql://localhost:3306/testdb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
*Controller.Java
#RequestMapping({"/users"})
public class UserController {
#Autowired
private UserService userService;
#GetMapping(path = {"/{id}"})
public User findOne(#PathVariable("id") int id){
return userService.findById(id);
}
}
UserService.java
public interface UserService {
User findById(int id);
}
UserServiceImpl.java
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository repository;
#Override
public User findById(int id) {
return repository.findOne(id);
}
}
UserRepository .java
public interface UserRepository extends Repository<User, Integer> {
User findOne(int id);
}
User.java
#Entity
#Table(name = "user")
public class User {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
private String firstName;
#Column
private String lastName;
#Column
private String email;
//setter and getter
}
Make request from browser or application.
http://localhost:8080/demo-user/users/1

How to count row table in JPA Query

I'm new to Spring Boot. I have a mysql database, I use a query to count row in my table. But it's not work, it still return my original table data. Can you help me check my code.
Here is my Entity:
#Entity
#Table(name = "act_id_membership", schema = "activiti", catalog = "")
#IdClass(ActIdMembershipEntityPK.class)
public class ActIdMembershipEntity {
private String userId;
private String groupId;
#Id
#Column(name = "USER_ID_")
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
#Id
#Column(name = "GROUP_ID_")
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ActIdMembershipEntity that = (ActIdMembershipEntity) o;
return Objects.equals(userId, that.userId) &&
Objects.equals(groupId, that.groupId);
}
#Override
public int hashCode() {
return Objects.hash(userId, groupId);
}
}
Here is my query:
#Repository
public interface MemershipRepository extends JpaRepository<ActIdMembershipEntity, String> {
#Query ("select new com.example.activiti_restful.dtos.UserMembership(i.userId, count(i)) from ActIdMembershipEntity i where i.userId ='kermit'")
UserMembership countMemberships(String userId);
}
Updated code:
My service class:
#Service
public class MembershipService {
#Autowired
private MemershipRepository repository;
public long count() {
return repository.count();
}
My resource class:
#RestController
public class MembershipResource {
#Autowired
private MembershipService membershipService;
#GetMapping("/membership")
public long list() {return membershipService.count();}
}
My custom JSON Object class:
public class UserMembership {
private String userId;
private long numberOfusers;
public UserMembership(String userId, long numberOfusers) {
this.userId = userId;
this.numberOfusers = numberOfusers;
}
}
MySQL Table:
act_id_membership
According repositories documentation using CrudRepository provides a method called count() that is one of the Superinterfaces which JpaRepository is implemented.
Based CrudRepository documentation says:
long count(); Returns the number of entities.
Then you should use CrudRepository method. In addition Remove Uppercase MembershipREPOSITORY, by java code convention, you have to use by following way MembershipRepository.
#Repository
public interface MembershipRepository extends JpaRepository <ActIdMembershipEntity, String> {
}
And use it in your Service:
#Service
public class MembershipService {
#Autowired
private MembershipRepository repo;
public long count() {
return repo.count();
}
}
UPDATED
Based on your requirement:
In Controller:
#RestController
public class MembershipResource {
#Autowired
private MembershipService membershipService;
#GetMapping("/membership")
public List<Object> list() { return membershipService.countMemberships();
}
}
In Service:
#Service
public class MembershipService {
#Autowired
private MemershipRepository repository;
public List<Object> countMemberships() {
return repository.countMemberships();
}
}
In Repository:
#Repository
public interface MemershipRepository extends JpaRepository<ActIdMembershipEntity, String> {
#Query ("select i.userId, count(i) from ActIdMembershipEntity i where i.userId ='kermit'")
List<Object> countMemberships();
}
*> Actually I want it return a json format like [{ name: kermit, value:6}]. Now it just return a number 6 only. How I can do that? Thank you!
First, create a class to wrap your data:
public class UserMembership {
private String userId;
private long numberOfUsers;
public UserMembership(String userId, long numberOfUsers) {
this.userId = userId;
this.numerOfUsers = numberOfUsers;
}
}
Then
#Repository
public interface MembershipRepository extends JpaRepository <ActIdMembershipEntity, String> {
#Query ("select new *****.UserMembership(i.userId, count(i)) from ActIdMembershipEntity i where i.userId = :userId")
UserMembership countMemberships(String userId);
}
*****: your full package name
Hope it help!

Spring Boot: Saving a one to many json request, foreign key is not saved automatically

I have 2 entities, Role and Resource. A role can have many resources.
#Entity
public class Resource {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(name="firstname")
private String firstName;
#Column(name="lastname")
private String lastName;
private String email;
#ManyToOne
#JoinColumn(name="roleId", nullable = false)
private Role role;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
#Entity
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Column(name = "rolename")
private String roleName;
#OneToMany(mappedBy = "role", cascade = CascadeType.ALL)
private List<Resource> resources;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public List<Resource> getResources() {
return resources;
}
public void setResources(List<Resource> resources) {
this.resources = resources;
}
}
I'm trying to save a Role object that has a resource in it. This is the body of my json in postman.
{
"roleName" : "Business Analyst",
"resources" : [{
"firstName" : "John",
"lastName" : "Doe",
"email" : "John#Doe.com"
}]
}
http post call in postman:
http://localhost:8080/app/admin/roles/role
Role Controller
#RestController
#RequestMapping(value="/admin/roles")
public class RoleController {
#Autowired
private RoleService roleService;
private static final Logger log = LoggerFactory.getLogger(RoleController.class);
#RequestMapping(value="/role", method = RequestMethod.POST)
public ResponseEntity<?> addRole(#RequestBody Role role, UriComponentsBuilder ucBuilder){
log.info("Adding Role {}" + role);
log.info("Adding Rolename:" + role.getRoleName());
roleService.addRole(role);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/admin/roles/role/{id}").buildAndExpand(role.getId()).toUri());
return new ResponseEntity<String> (headers,HttpStatus.CREATED);
}
#RequestMapping(value="role", method = RequestMethod.GET)
public ResponseEntity<List<Role>> listAllRoles(){
List<Role> roles = roleService.getAllRoles();
return new ResponseEntity<List<Role>>(roles, HttpStatus.OK);
}
}
RoleRepository
public interface RoleRepository extends CrudRepository<Role, Integer> {
}
RoleService
public interface RoleService {
public void addRole(Role role);
}
RoleServiceImpl
#Service
public class RoleServiceImpl implements RoleService {
#Autowired
private RoleRepository roleRepository;
#Override
public void addRole(Role role) {
roleRepository.save(role);
}
}
Whats happening is, the role Business Analyst gets save in the roleName field of Role table. The id of the said row is auto generated. At the same time, the resource with firstName = John, lastName = Doe and email = John#Doe.com gets save in the Resource table.
However, the role_id is not being saved automatically in the Resource table so now it is null ( the table Resource has the role_id set to nullable ). I was expecting that when I do the json post, the data will be automatically saved in the Role table and also the Resource table. Both of these are happening except that the role_id is not being saved. What did I miss?
Change addRole like below :
public void addRole(Role role) {
for(Resource resource: role.getResources()){
resource.setRole(role);
}
roleRepository.save(role);
}

SPRING+JPA+HIBERNATE Deleting a child deletes the parent object too

I have two tables, Enterprises and Appliance in unidirectional one to many association.
When I try to delete any enterprise, it deletes its corresponding appliances too, which is the expected behavior.
Now if I try to delete any appliance, its corresponding enterprise gets deleted as well!!
This is neither expected nor am I able to figure out how to solve this.
I wish that if I delete an Appliance only that appliance should get deleted not, the Enterprise the appliance belongs too!!
Enterprise Class:
#Entity
#Table(name="Enterprises")
public class Enterprises implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id", nullable=false, unique=true)
private Long id;
#Column(name="EntpName")
private String entpName;
#Column(name="ContactPerson")
private String contactPerson;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="CreatedDate", nullable=false)
private Date createdDate;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="ModifiedDate")
private Date modifiedDate;
public Enterprises() { }
public Enterprises(Long id) {
this.id = id;
}
public Enterprises(String entpName, String contactPerson) {
this.entpName = entpName;
this.contactPerson = contactPerson;
this.setCreatedDate();
}
// Getter and setter methods
public Long getId() {
return id;
}
public void setId(Long value) {
this.id = value;
}
public String getEntpName() {
return entpName;
}
public void setEntpName(String value) {
this.entpName = value;
}
public String getContactPerson() {
return contactPerson;
}
public void setContactPerson(String value) {
this.contactPerson = value;
}
public Date getCreatedDate() { return createdDate; }
#PrePersist
public void setCreatedDate() {
this.createdDate = new Date();
}
public Date getModifiedDate() { return modifiedDate; }
#PreUpdate
public void setModifiedDate() {
this.modifiedDate = new Date();
}
}
Appliance Class:
#Entity
#Table(name="Appliance")
public class Appliance {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id", nullable=false, unique=true)
private Long id;
#Column(name="ApplianceName")
private String AppName;
#Column(name="Parameter1")
private String param1;
#Column(name="Parameter2")
private String param2;
#Column(name="Parameter3")
private String param3;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="CreatedDate", nullable=false)
private Date createdDate;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="ModifiedDate")
private Date modifiedDate;
#ManyToOne(cascade = {CascadeType.REMOVE, CascadeType.REFRESH}, fetch = FetchType.LAZY)
#JoinColumn(name="Enterprises_id", referencedColumnName = "id")
#OnDelete(action= OnDeleteAction.CASCADE)
private Enterprises enterprise;
public Enterprises getEnterprise() {
return enterprise;
}
public void setEnterprise(Enterprises enterprise) {
this.enterprise = enterprise;
}
// ------------------------
// PUBLIC METHODS
// ------------------------
public Appliance() { }
public Appliance(Long id) {
this.id = id;
}
public Appliance(String AppName, String param1, String param2, String param3) {
this.AppName = AppName;
this.param1 = param1;
this.param2 = param2;
this.param3 = param3;
this.setCreatedDate();
}
// Getter and setter methods
public Long getId() {
return id;
}
public void setId(Long value) {
this.id = value;
}
public String getAppName() {
return AppName;
}
public void setAppName(String value) {
this.AppName = value;
}
public String getparam1() {
return param1;
}
public void setparam1(String value) {
this.param1 = value;
}
public String getparam2() {
return param2;
}
public void setparam2(String value) {
this.param2 = value;
}
public String getparam3() {
return param3;
}
public void setparam3(String value) {
this.param3 = value;
}
public Date getCreatedDate() { return createdDate; }
#PrePersist
public void setCreatedDate() {
this.createdDate = new Date();
}
public Date getModifiedDate() { return modifiedDate; }
#PreUpdate
public void setModifiedDate() {
this.modifiedDate = new Date();
}
}
My controller:
ApplianceUserController:
#Controller
#RequestMapping("/")
public class ApplianceUserController {
#Autowired
private ApplianceRepository appliancerepo;
#Autowired
private UserRepository userrepo;
#RequestMapping(value = "{id}/list", method = RequestMethod.GET)
#ResponseBody
public LinkedList<List> listStuff(#PathVariable("id") Enterprises id) {
List<Appliance> appliances = appliancerepo.findApplianceByEnt_id(id);
List<Users> users = userrepo.findUsersByEnt_id(id);
LinkedList<List> together = new LinkedList<List>();
together.add(appliances);
together.add(users);
return together;
}
#RequestMapping(value="{idd}/appliance/add" , method = RequestMethod.POST)
#ResponseBody
Appliance addAppliance(#PathVariable("idd") Enterprises idd , #RequestBody Appliance appliance) {
appliance.setEnterprise(idd);
appliance.setCreatedDate();
return appliancerepo.save(appliance);
}
#RequestMapping(value = "appliance/update/{id}", method = RequestMethod.PUT)
#ResponseBody
Appliance updateAppliance(#PathVariable("id") Long id, #RequestBody Appliance appliance) {
Appliance applianceOld= appliancerepo.findById(id);
applianceOld.setAppName(appliance.getAppName());
applianceOld.setparam1(appliance.getparam1());
applianceOld.setparam2(appliance.getparam2());
applianceOld.setparam3(appliance.getparam3());
applianceOld.setModifiedDate();
return appliancerepo.save(applianceOld);
}
#RequestMapping(value = "appliance/delete/{id}", method = RequestMethod.DELETE)
#ResponseBody
void deleteAppliance(#PathVariable("id") Long id) {
appliancerepo.delete(id);
}
#RequestMapping(value = "appliance/{id}", method = RequestMethod.GET)
#ResponseBody
Appliance getA(#PathVariable("id") Long id) {
Appliance appliance=appliancerepo.findAppliance(id);
System.out.println(appliance);
return appliance;
}
}
PS: Yes, cascade update and delete is ON for the foreign keys in the MySql database!!!!
Please inform me, if you need any other code.
UPDATE:
SOLVED
For future reference by anyone:
Needed to remove the #OnDelete line and and the cascade property from #ManyToOne in the Appliance class!!

MOXy. generate JSON, doesn't contain reference class

I used Eclipselink MOXy to convert my POJO(using JPA) to json. and it's work.
but i have one problem. I have pojo class MAccount contain many to one relation to class MProduct,. when I convert to json, result show that class MAccount not in class MProduct.
here my class MAccount implementation:
#XmlRootElement
#Entity
#Table(name="m_account")
public class MAccount extends BaseObject implements Serializable {
private static final long serialVersionUID = UUID.randomUUID().getMostSignificantBits();
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#XmlID
private Long id;
#Column(name="account_id")
private String accountId;
#Column(name="card_number")
private String cardNumber;
//bi-directional many-to-one association to Product
#ManyToOne
#JoinColumn(name="m_product_id")
#XmlIDREF
private MProduct mProduct;
public MCustomerAccount() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getAccountId() {
return this.accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public MProduct getMProduct() {
return this.mProduct;
}
public void setMProduct(MProduct mProduct) {
this.mProduct = mProduct;
}
// Imlement base object method
...
}
here my class MProduct implementation:
#XmlRootElement
#Entity
#Table(name="m_product")
public class MProduct extends BaseObject implements Serializable {
private static final long serialVersionUID = UUID.randomUUID().getMostSignificantBits();
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#XmlID
private Long id;
#Column(name="product_code")
private String productCode;
#Column(name="product_name")
private String productName;
//bi-directional many-to-one association to MAccount
#OneToMany(mappedBy="mProduct")
#XmlInverseReference(mappedBy="mProduct")
private Set<MAccount> mAccountList;
public MProduct() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getProductCode() {
return this.productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public String getProductName() {
return this.productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Set<MAccount> getMAccountList() {
return this.mAccountList;
}
public void setMAccountList(Set<MAccount> mAccountList) {
this.mAccountList = mAccountList;
}
// Imlement base object method
...
}
And generate JSON from MAccount class
{"MAccount":[
{"#type":"mAccount","id":"6","accountId":"05866039901"},
{"#type":"mAccount","id":"7","accountId":"25600036290"}]
}
there is no MProduct in there, the correct json result should be like below
{"MAccount":[
{"#type":"mAccount","id":6,"accountId":"05866039901","MProduct":{"#type":"mProduct","productCode":"T01","productName":"Book"}},
{"#type":"mAccount","id":7,"accountId":"25600036290","MProduct":{"#type":"mProduct","productCode":"T02","productName":"Pen"}}]
}
Is Anyone know how to solve this problem
Thank's b4
Because you are annotating the field, there is a chance that JPA has not populated that field yet due to lazy loading. If you annotate the property (get/set) instead do you still see this behaviour?
For more information on #XmlInverseReference see:
http://bdoughan.blogspot.com/2010/07/jpa-entities-to-xml-bidirectional.html