Data mismatch between Json response and database - mysql

I'm retrieving data from mysql using spring boot, hibernate and producing the response as REST service. But while checking in Postman the data mismatches. Here is my code.
Controller Class:
#RestController
public class NotificationController<T> extends RestUtils<T> {
#Autowired
NotificationService<T> service;
#RequestMapping(value = "/notification/getNotifications", method = RequestMethod.POST, headers = "Accept=application/json")
public #ResponseBody Object getNotifications(#RequestBody NotificationBean notificationBean) {
try {
return getSuccessResponse(service.getNotifications(notificationBean), "Total Count: ",
service.getNotificationsCount(notificationBean));
} catch (StudawnException e) {
return getErrorResponse(e.getMessage());
}
}
}
Service Implementation:
#Service
public class NotificationServiceImpl<T> implements NotificationService<T> {
#Autowired
NotificationRepository notificationRepository;
#SuppressWarnings("deprecation")
#Transactional
#Override
public Object getNotifications(NotificationBean notificationBean) throws StudawnException {
Sort sort = new Sort(new Sort.Order(Direction.DESC, "dateCreated"));
Pageable pageable = new PageRequest(notificationBean.getPage(), notificationBean.getSize(), sort);
return notificationRepository.findNotificationsByStudentId(notificationBean.getStudentId(), pageable);
}
}
Repository:
#Repository
public interface NotificationRepository<T> extends JpaRepository<Notification, Integer> {
#Query(NotificationQuery.findNotificationsByStudentId)
List<Notification> findNotificationsByStudentId(#Param("studentId") Integer studentId, Pageable pageable);
#Query(NotificationQuery.findNotificationsCountByStudentId)
Integer findNotificationsCountByStudentId(#Param("studentId")Integer studentId);
}
Query class:
public class NotificationQuery {
public static final String findNotificationsByStudentId = "select n from #{#entityName} n where n.student.studentId = :studentId and n.isActive=true";
public static final String findNotificationsCountByStudentId = "select count(n) from #{#entityName} n where n.student.studentId=:studentId and n.isActive=true";
}
Model class
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#Entity
#Table(name = "notification")
#EntityListeners(AuditingEntityListener.class)
#JsonIgnoreProperties(value = { "dateCreated" }, allowGetters = true)
public class Notification {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "notification_id")
private int notificationId;
#ManyToOne
#JoinColumn(name = "student_id")
private Student student;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created_date", nullable = false, updatable = false)
#CreatedDate
private Date dateCreated;
#Column(name = "is_active")
private boolean isActive;
#Column(name = "has_read")
private boolean hasRead;
#Column(name = "message", length = 150)
private String message;
public int getNotificationId() {
return notificationId;
}
public void setNotificationId(int notificationId) {
this.notificationId = notificationId;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
public boolean isActive() {
return isActive;
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}
public boolean isHasRead() {
return hasRead;
}
public void setHasRead(boolean hasRead) {
this.hasRead = hasRead;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Json Request
{
"studentId":101,
"page":0,
"size":10
}
Json Response
The date in 'dateCreated' field mismatch with database. The actual date in DB is '2018-03-06' but in response it is '2018-03-05'
{
"response": [
{
"notificationId": 4,
"student": {
"studentId": 101,
"studawnId": "1234",
"firstName": "arun",
"lastName": "kumar",
"emailId": "arun#xyz.com",
"mobileNumber": "987654",
"dateOfBirth": "1990-03-02T18:30:00.000+0000",
"gender": "male",
"profilePicture": "Pictures",
"hasTermsAccepted": true,
"dateCreated": "2018-03-02T18:30:00.000+0000",
"dateModified": "2018-03-02T18:30:00.000+0000",
"aadhaarNumber": "565497",
"addressOne": "adyar",
"addressTwo": "chennai",
"pincode": "600096",
"tickets": [],
"active": true,
"firstTimeLogin": true,
"school": true,
"college": true
},
"dateCreated": "2018-03-05T18:30:00.000+0000",
"hasRead": true,
"message": "User 1 has sent a msg to you",
"active": true
}
]
}
Thanks in advance.

I think you should check timezones. It looks like you have saved the date in your local timezone, but when you retrieve it from database and send to client you use GMT timezone.

Related

Postman SpringBoot RestApi status code 415 on POSTrequest

I have just started studying Springboot. Everything worked fine until I run into this problem. I've searched every StackOverFlow topic and internet overall and none resolved my problems. I tried to set Content-Type and Accepts the right way but it still didn't work.
UserController:
package com.example.carnet.api;
import com.example.carnet.model.User;
import com.example.carnet.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
#RestController
#RequestMapping("/carnet/user")
public class UserController {
private final UserService userService;
#Autowired
public UserController(UserService userService) {
this.userService = userService;
}
#GetMapping("/all")
public List<User> getUsers() {
return userService.getUsers();
}
#GetMapping(path = "/{email}")
public User getUserByEmail(#PathVariable("email") String email) {
return userService.getUserByEmail(email);
}
#GetMapping("/validate")
public boolean validateUser(#RequestParam("email") String email, #RequestParam("password") String password) {
return userService.validateUser(email, password);
}
#PostMapping("/add")
public void addUser(#RequestBody User user) {
userService.addUser(user);
}
#DeleteMapping(path = "/{id}")
public void deleteUserById(#PathVariable("id") int id) {
userService.deleteUserById(id);
}
#PutMapping
public void updatePassword(#RequestBody User user) {
userService.updatePassword(user);
}
}
User Model:
package com.example.carnet.model;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.sql.Date;
import java.util.List;
#Table(name = "users")
#Entity
public class User {
#Id
private int user_id;
private String email;
private String password;
private String name;
private String surname;
private Date birth_date;
#OneToMany(mappedBy = "user")
#JsonManagedReference
private List<Rental> rentals;
public User() {
}
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public Date getBirth_date() {
return birth_date;
}
public void setBirth_date(Date birth_date) {
this.birth_date = birth_date;
}
}
Error after doing POST request with Postman:
{
"timestamp": "2020-05-06T19:01:16.498+0000",
"status": 415,
"error": "Unsupported Media Type",
"message": "Content type 'application/json;charset=UTF-8' not supported",
"path": "/carnet/user/add"
}
SOLVED: Removing #JsonManagedReference from User Model solved the problem!
This problem is because of the #JsonManagedReference in your model class,
Try interchanging #JsonBackReference and #JsonManagedReference. It should work.
Just explore the documentation for more info.
This is one similar issue reported for the same case.

Can't parse JSON object and insert it into database

I have a problem with JSON object parsing. The JSON represents an order placed by user.
This had worked before, but adding additional Entity/DTO to project caused some problems. To be more specific, JSON looks as below:
{
"orderElements": [
{
"product": {
"id": 3,
"name": "xxx",
"description": "yyy",
"category": {
"id": 2,
"name": "xxx"
},
"price": 11,
"count": 1
},
"quantity": 1
}
],
"user": {
"id": 110,
"lastName": "xxx",
"firstName": "xxx",
"addressLine": "xxx",
"city": "xxx",
"country": "xxx",
"zipCode": "123456",
"phoneNumber": "1234567",
"password": "xxxx",
"email": "xxxx",
"roles": [
"USER"
]
},
"orderPlaceTime": null,
"deliveryAddress": {
"street": "xxx",
"city": "xxx",
"zipCode": "xxx"
}
}
If sent without "deliveryAddress" part, JSON is being parsed correctly and everything worked just fine. But trying to send JSON with "deliveryAddress" and all it's contents results in NullPointerException.
Although debugging frontend shows that whole JSON is filled correctly - street, city and zipCode fields contain all data that has been put by user (this above is exactly what is send by "POST" - "orderPlaceTime" is filled on backend side by LocalDateTime.now() function).
ORDER
#Entity
#Table(name = "carts")
public class Order extends AbstractEntity {
#Fetch(FetchMode.SELECT)
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "id_order")
#JsonIgnore
private Set<OrderElement> orderElements;
#Column
private LocalDateTime orderPlaceTime;
#ManyToOne
#JoinColumn(name = "id_user")
private User user;
#ManyToOne
#JoinColumn(name = "id_delivery")
private DeliveryAddress deliveryAddress;
public DeliveryAddress getDeliveryAddress() {
return deliveryAddress;
}
public void setDeliveryAddress(DeliveryAddress deliveryAddress) {
this.deliveryAddress = deliveryAddress;
}
public Set<OrderElement> getOrderElements() {
return orderElements;
}
public void setOrderElements(Set<OrderElement> orderElements) {
this.orderElements = orderElements;
}
public LocalDateTime getOrderPlaceTime() {
return orderPlaceTime;
}
public void setOrderPlaceTime(LocalDateTime orderPlaceTime) {
this.orderPlaceTime = orderPlaceTime;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
DELIVERYADDRESS
#Entity
#Table(name = "delivery_address")
public class DeliveryAddress extends AbstractEntity {
#Column
private String street;
#Column
private String city;
#Column
private String zipCode;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
ORDER CONVERTER
#Component
public class OrderConverter implements Converter<Order, OrderDTO> {
private final OrderElementConverter orderElementConverter;
private final DeliveryAddressConverter deliveryAddressConverter;
private final UserConverter userConverter;
public OrderConverter(OrderElementConverter orderElementConverter, DeliveryAddressConverter deliveryAddressConverter, UserConverter userConverter) {
this.orderElementConverter = orderElementConverter;
this.deliveryAddressConverter = deliveryAddressConverter;
this.userConverter = userConverter;
}
#Override
public Order convertToEntity(OrderDTO dto) {
Order order = new Order();
order.setId(dto.getId());
order.setUser(userConverter.convertToEntity(dto.getUser()));
order.setOrderPlaceTime(now());
Set<OrderElement> entitySet = new HashSet<>();
for (OrderElementDTO o : dto.getOrderElements()) {
entitySet.add(orderElementConverter.convertToEntity(o));
}
order.setOrderElements(entitySet);
// this below throws NullPointerException --> dto.getDeliveryAddressDTO();
order.setDeliveryAddress(deliveryAddressConverter.convertToEntity(dto.getDeliveryAddressDTO()));
return order;
}
}
DELIVERY ADRESS CONVERTER
#Component
public class DeliveryAddressConverter implements Converter<DeliveryAddress, DeliveryAddressDTO> {
#Override
public DeliveryAddress convertToEntity(DeliveryAddressDTO dto) {
DeliveryAddress deliveryAddress = new DeliveryAddress();
deliveryAddress.setId(dto.getId());
deliveryAddress.setCity(dto.getCity());
deliveryAddress.setZipCode(dto.getZipCode());
deliveryAddress.setStreet(dto.getStreet());
return deliveryAddress;
}
}
And I have no idea why deliveryAddress is null if it is sent by frontend correctly.
Thank you for all answers and suggestions
EDIT
It turned out as pointed by JB Nizet fields in OrderDTO had "deliveryAddressDTO" rather than "deliveryAddress". Cutting "DTO" from names fixed the issue:
public class OrderDTO extends AbstractDTO {
private Set<OrderElementDTO> orderElements;
private LocalDateTime orderPlaceTime;
private UserDTO user;
private DeliveryAddressDTO deliveryAddress;
// private DeliveryAddressDTO deliveryAddressDTO; <-- wrong name, methods also aligned
public DeliveryAddressDTO getDeliveryAddress() {
return deliveryAddress;
}
public void setDeliveryAddressDTO(DeliveryAddressDTO deliveryAddress) {
this.deliveryAddress = deliveryAddress;
}
public Set<OrderElementDTO> getOrderElements() {
return orderElements;
}
public void setOrderElements(Set<OrderElementDTO> orderElements) {
this.orderElements = orderElements;
}
public LocalDateTime getOrderPlaceTime() {
return orderPlaceTime;
}
public void setOrderPlaceTime(LocalDateTime orderPlaceTime) {
this.orderPlaceTime = orderPlaceTime;
}
public UserDTO getUser() {
return user;
}
public void setUser(UserDTO user) {
this.user = user;
}
}
It turned out as pointed by JB Nizet fields in OrderDTO had "deliveryAddressDTO" rather than "deliveryAddress". Cutting "DTO" from names fixed the issue:
public class OrderDTO extends AbstractDTO {
private Set<OrderElementDTO> orderElements;
private LocalDateTime orderPlaceTime;
private UserDTO user;
private DeliveryAddressDTO deliveryAddress;
// private DeliveryAddressDTO deliveryAddressDTO; <-- wrong name, methods also aligned
public DeliveryAddressDTO getDeliveryAddress() {
return deliveryAddress;
}
public void setDeliveryAddressDTO(DeliveryAddressDTO deliveryAddress) {
this.deliveryAddress = deliveryAddress;
}
public Set<OrderElementDTO> getOrderElements() {
return orderElements;
}
public void setOrderElements(Set<OrderElementDTO> orderElements) {
this.orderElements = orderElements;
}
public LocalDateTime getOrderPlaceTime() {
return orderPlaceTime;
}
public void setOrderPlaceTime(LocalDateTime orderPlaceTime) {
this.orderPlaceTime = orderPlaceTime;
}
public UserDTO getUser() {
return user;
}
public void setUser(UserDTO user) {
this.user = user;
}
}
Also id_delivery issue has been fixed by JB Nizet, as well - adding cascade.ALL annotation to the ManyToOne solved all problems.
Thank you!

How to rename json objects(variables) name in spring boot

Hello I am new to spring boot and JSON and need help in renaming the variable name coming in response.
Consider this as a input
"1": {
"id": "1",
"firstName": "Cdgdghirayu",
"lastName": "Sinfsdgdgghvi",
"age": 23
}
Now in respone I need in this format
"1": {
"Roll number": "1",
"firstName": "Cdgdghirayu",
"lastName": "Sinfsdgdgghvi",
"age": 23
}
can we map "id" to "roll number" in some way?
How to achieve this in spring-boot?
Thanks in advance
upadte-
This is my model class
package model;
import javax.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.annotation.JsonProperty;
#XmlRootElement
public class Person {
#JsonProperty("Roll Number")
private String id;
private String firstName;
private String lastName;
private int age;
public Person() {
super();
}
public Person(String id, String firstName, String lastName, int age) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String 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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
This is my service class
Here in addPerson() function I have to set id as its taking id as null..
package service;
import java.util.Hashtable;
import org.springframework.stereotype.Service;
import model.Person;
#Service
public class PersonService {
Hashtable<String,Person> persons=new Hashtable<String,Person>();
public PersonService(){
Person p=new Person();
p.setId("1");
p.setFirstName("Chirayu");
p.setLastName("Singhvi");
p.setAge(23);
persons.put("1",p);
p=new Person();
p.setId("2");
p.setFirstName("Himanshu");
p.setLastName("Singhvi");
p.setAge(20);
persons.put("2",p);
}
public Person getPerson(String id){
if(persons.containsKey(id))
return persons.get(id);
else return null;
}
public Hashtable<String,Person> getAll(){
return persons;
}
public Person addPerson(Person person){
persons.put(person.getId(),person);
return person;
}
public Person updatePerson(Person person){
if(person.getId().equals("0")){
return null;
}
persons.put(person.getId(),person);
return person;
}
public Person removePerson(String id) {
return persons.remove(id);
}
My controller class
package controller;
import java.util.Hashtable;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import model.Person;
import service.PersonService;
#RestController
#RequestMapping("/persons")
public class PersonController {
static final Logger log = Logger.getLogger(PersonController.class.getName());
PersonController(){
log.info("entering controller class");
}
#Autowired
PersonService personService;
#RequestMapping("/all")
public Hashtable<String,Person> getAll(){
log.info("getting all person details");
System.out.println("syso is working");
return personService.getAll();
}
#RequestMapping(value="/all",method=RequestMethod.POST,
produces=MediaType.APPLICATION_JSON_VALUE,
consumes=MediaType.APPLICATION_JSON_VALUE )
#ResponseBody
public Person addPerson(#RequestBody Person person){
log.info("Adding person with id "+person.getId());
person.getId();
return personService.addPerson(person);
}
#RequestMapping(value="/{id}",method=RequestMethod.PUT,
produces=MediaType.APPLICATION_JSON_VALUE,
consumes=MediaType.APPLICATION_JSON_VALUE )
#ResponseBody
public Person updatePerson(#PathVariable("id") String id,
#RequestBody Person person){
person.setId(id);
log.info("Updating a partcular person details with id "+id);
return personService.updatePerson(person);
}
#RequestMapping(value="/{id}",method=RequestMethod.DELETE)
public void removePerson(#PathVariable("id") String id){
log.info("Removing the person details with id "+id);
personService.removePerson(id);
}
#RequestMapping("/{id}")
public Person getPerson(#PathVariable("id") String id){
log.info("getting person details with id "+id);
return personService.getPerson(id);
}
public void setDthDao(PersonService dao) {//for testing purpose
personService=dao;
}
Now in SOAPUI testing(writing text as snapshots are not uploading)
for GET request : endpoint-http://localhost:8080 :Resource-/persons/all
response-
{
"2": {
"firstName": "Himanshu",
"lastName": "Singhvi",
"age": 20,
"Roll Number": "2"
},
"1": {
"firstName": "Chirayu",
"lastName": "Singhvi",
"age": 23,
"Roll Number": "1"
}
}
Now for Post- : endpoint-http://localhost:8080 :Resource-/persons/all
Mediatype-
{
"firstName": "Rahul",
"lastName": "Jain",
"age": 23,
"id": "6"
}
Response what I am getting
{
"timestamp": 1469790685110,
"status": 500,
"error": "Internal Server Error",
"exception": "java.lang.NullPointerException",
"message": "No message available",
"path": "/persons/all"
}
Response that I want
{
"firstName": "Rahul",
"lastName": "Jain",
"age": 23,
"Roll number": "6"
}
Assuming you have a getter method for the id property, you can try adding the com.fasterxml.jackson.core dependency to your project and annotating your method like this:
#JsonProperty("Roll Number")
public Long getId () {
return id;
}
Finally got it right
just made following changes in my model class.
#JsonProperty("Roll Number")
private String id;
#JsonProperty("Roll Number")
public String getId() {
return id;
}
#JsonProperty("id")
public void setId(String id) {
this.id = id;
}

How to get rest response that contains only certain object's json?

My goal is to get rest services working on spring boot web application.
But I am struggling with finding out how to tell response to include object's json only.
To be more precise, when calling http://localhost:8080/api/db/Keyboard/2, I intend to receive object with id 2 in json format and only:
{
"id": 2,
"language": "en"
}
But instead I get:
{
"status": 200,
"entity": {
"id": 2,
"language": "en"
},
"metadata": {},
"length": -1,
"allowedMethods": [],
"cookies": {},
"headers": {},
"actualEntity": {
"id": 2,
"language": "en"
},
"links": [],
"statusInfo": {
"reasonPhrase": "OK",
"statusCode": 200,
"family": "SUCCESSFUL"
},
"stringHeaders": {}
}
Clearly response contains too much info. Only the entity part is needed. How to reach intended result / adjust conditionally the response?
Below some files that might be relevant.
TestController.java:
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import main.domain.DaoApi;
import main.domain.Keyboard;
#RestController
public class TestController<T, K> {
private final static Map<String, Class<?>> tableClassMap = new HashMap<>();
#Autowired
private DaoApi<T, K> daoApi;
static {
addEntryTableClassMap(Keyboard.class);
}
#RequestMapping(value = "/api/db/{tableName}/{id}", method = RequestMethod.GET)
public Response getById(#PathVariable(value = "tableName") String tableName, #PathVariable(value = "id") Integer id) {
ResponseBuilder responseBuilder;
T entity = (T) daoApi.findById((Class<T>) getClassFromTableClassMap(tableName), id);
if (entity != null) {
responseBuilder = Response.ok(entity);
} else {
responseBuilder = Response.status(Status.NOT_FOUND);
}
return responseBuilder.build();
}
private static <C> void addEntryTableClassMap(Class<C> clazz) {
tableClassMap.put(clazz.getSimpleName().toLowerCase(), clazz);
}
private static <C> Class<C> getClassFromTableClassMap(String tableName) {
return (Class<C>) tableClassMap.get(tableName.toLowerCase());
}
}
Keyboard.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.transaction.annotation.Transactional;
#Transactional
#Entity
#Table(name = "keyboard")
public class Keyboard {
#Id
#Column(updatable = false)
private int id;
private String language;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}
DaoApi.java:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class DaoApi<T, K> {
#Autowired
SessionFactory sessionFactory;
public T findById(Class<T> clazz, Integer id) {
Session session = sessionFactory.openSession();
T t = (T) session.get(clazz, id);
session.close();
return t;
}
}
Received comment that helped me to solution:
#RequestMapping(value = "/api/db/{tableName}/{id}", method = RequestMethod.GET)
public T getById(#PathVariable(value = "tableName") String tableName, #PathVariable(value = "id") Integer id) {
ResponseBuilder responseBuilder;
T entity = (T) daoApi.findById((Class<T>) getClassFromTableClassMap(tableName), id);
if (entity != null) {
responseBuilder = Response.ok(entity);
return (T) responseBuilder.build().getEntity();
} else {
responseBuilder = Response.status(Status.NOT_FOUND);
//some additional code here
return (T) responseBuilder.build();
}
}

Java object to JSON using GSON gives stackoverflow error

I am trying to use GSON to convert a java object, in list format, to JSON, I have tried a few ways, but am running into the same error.
1st attempt
List<Techinv> techs = UserUtil.getTechModels(group, org);
Gson gson = new Gson();
String json = gson.toJson(techs);
2nd attempt
List<Techinv> techs = UserUtil.getTechModels(group, org);
Type listType = new TypeToken<List<Techinv>>() {}.getType();
Gson gson = new Gson();
String json = gson.toJson(techs, listType);
3rd attempt
List<Techinv> techs = UserUtil.getTechModels(group, org);
GsonBuilder gsonBuilder = new GsonBuilder();
new GraphAdapterBuilder()
.addType(Techinv.class)
.registerOn(gsonBuilder);
Gson gson = gsonBuilder.create();
String json = gson.toJson(techs);
All of the above fail, with either a stackoverflow error or a can't convert java int (one of the members in my Techinv class) to a java vector, all in the GSON library.
Please tell me I am missing something simple in all these examples :)
Techinv class (if required)
package org.cchit.inv.model;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* The persistent class for the techinv database table.
*
*/
#Entity
#NamedNativeQueries ({
#NamedNativeQuery(name="Techinv.deleteByOrgId",
query="DELETE FROM techinv where org_id = ?")
})
#NamedQueries ({
#NamedQuery(name="Techinv.removeUser",
query="UPDATE Techinv t SET user_id = 0 where t.id = :techid"),
#NamedQuery(name="Techinv.getAllByOrg",
query="SELECT p FROM Techinv p where p.organization.liferayId = :orgid"),
#NamedQuery(name="Techinv.getById",
query="SELECT t FROM Techinv t where t.id = :id"),
#NamedQuery(name="Techinv.getByProdOrg",
query="SELECT p FROM Techinv p where p.organization.liferayId = :orgid and p.product.id = :prodid"),
#NamedQuery(name="Techinv.delete",
query="DELETE FROM Techinv t where t.id = :id")
})
#Table(name="techinv")
public class Techinv implements Serializable {
private static final long serialVersionUID = 1L;
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name="mu_mask")
private long muMask;
#Column(name="mu_assigned_mask")
private long muAssignedMask;
#Column(name="mu_asked_assign_mask")
private long muAskedAssignedMask;
#Column(name="mu_cert_mask")
private long muWillCertMask;
#Column(name="mu_ask_will_cert_mask")
private long muAskedWillCertMask;
#Column(name="certType")
private String certType;
#Temporal(TemporalType.DATE)
#Column(name="Apply_date")
private Date applyDate;
#Temporal(TemporalType.DATE)
#Column(name="Cert_date")
private Date certDate;
#Lob()
private String notes;
//bi-directional many-to-one association to OrgUser
#ManyToOne
#JoinColumn(name="user_id")
private OrgUser orgUser;
//bi-directional many-to-one association to Organization
#ManyToOne
#JoinColumn(name="org_id")
private Organization organization;
//bi-directional many-to-one association to Product
#ManyToOne
#JoinColumn(name="prod_id")
private Product product;
//bi-directional many-to-one association to Certification
#ManyToOne
#JoinColumn(name="cert_id")
private Certification certification;
public void setCertification(Certification certification) {
this.certification = certification;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public Techinv() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getNotes() {
return this.notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public OrgUser getOrgUser() {
return this.orgUser;
}
public void setOrgUser(OrgUser orgUser) {
this.orgUser = orgUser;
}
public Organization getOrganization() {
return this.organization;
}
public void setOrganization(Organization organization) {
this.organization = organization;
}
public long getMuMask() {
return muMask;
}
public void setMuMask(long muMask) {
this.muMask = muMask;
}
public long getMuAssignedMask() {
return muAssignedMask;
}
public void setMuAssignedMask(long muAssigned) {
this.muAssignedMask = muAssigned;
}
public Certification getCertification() {
return certification;
}
public long getMuWillCertMask() {
return muWillCertMask;
}
public void setMuWillCertMask(long muWillCertMask) {
this.muWillCertMask = muWillCertMask;
}
public long getMuAskWillCertMask() {
return muAskedWillCertMask;
}
public void setMuAskedWillCertMask(long muAskedWillCertMask) {
this.muAskedWillCertMask = muAskedWillCertMask;
}
/**
* This will set the question to true. Once asked and answered, this cannot be unset.
* #param mu
*/
public void setMuAskedAssignedMask(Mu mu) {
this.muAskedAssignedMask |= mu.getMask();
}
public boolean isCertified(Mu mu) {
return getCertification() != null && (getCertification().getMuMask() & mu.getMask()) > 0;
}
public boolean isAssigned(Mu mu) {
return (getMuAssignedMask() & mu.getMask()) > 0;
}
public boolean hasAskedToCertify(Mu mu) {
return isAssigned(mu) && !isCertified(mu) && (getMuAskWillCertMask() & mu.getMask()) > 0;
}
public boolean isWillCertify(Mu mu) {
return hasAskedToCertify(mu) && (getMuWillCertMask() & mu.getMask()) > 0;
}
public boolean hasMu(Mu mu) {
return (getMuMask() & mu.getMask()) > 0;
}
public boolean hasAskedToAssign(Mu mu) {
return (muAskedAssignedMask & mu.getMask()) > 0;
}
public String getCertType() {
return certType;
}
public void setCertType(String certType) {
this.certType = certType;
}
public Date getApplyDate() {
return applyDate;
}
public void setApplyDate(Date applyDate) {
this.applyDate = applyDate;
}
public Date getCertDate() {
return certDate;
}
public void setCertDate(Date certDate) {
this.certDate = certDate;
}
}
You should check for circular references in your serialized classes and mark the appropriate properties #Transient. Post your TechModel class if you want help with that.
edit: as using #Transient is not an option for you , use Gson's #Expose .
From the GSON user guide :
This feature provides a way where you can mark certain fields of your
objects to be excluded for consideration for serialization and
deserialization to JSON. To use this annotation, you must create Gson
by using new
GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(). The
Gson instance created will exclude all fields in a class that are not
marked with #Expose annotation.
Type listType = new TypeToken<ArrayList<Techinv>>() {}.getType();
You may try out the standard implementation of the Java API for JSON processing which is part of J2EE.
I don't have access to your beans OrgUser, Organization, Product, and Certification. So I assume that each of them comprises an id and a name.
For your List<Techinv> techList.
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
List<Techinv> techList = new ArrayList<Techinv>();
for (int i = 1; i <= 3; i++) {
Techinv tech = new Techinv(i, 1L, 2L, 3L, 4L, 5L, "cert",
new Date(), new Date(), "notes", new OrgUser(i, "orguser"),
new Organization(i, "organization"), new Product(i,
"product"), new Certification(i, "certification"));
techList.add(tech);
}
Techinv[] techArr = techList.toArray(new Techinv[techList.size()]);
JsonArrayBuilder techArrBuilder = Json.createArrayBuilder();
for (Techinv tech : techArr) {
JsonObjectBuilder jsonObject = Json.createObjectBuilder()
.add("id", tech.getId())
.add("muMask", tech.getMuMask())
.add("muAssignedMask", tech.getMuAssignedMask())
.add("muAskedAssignedMask", tech.getMuAskedAssignedMask())
.add("muWillCertMask", tech.getMuWillCertMask())
.add("muAskedWillCertMask", tech.getMuAskedWillCertMask())
.add("certType", tech.getCertType())
.add("applyDate", sdf.format(tech.getApplyDate()))
.add("certDate", sdf.format(tech.getCertDate()))
.add("notes", tech.getNotes())
.add("OrgUser", Json.createObjectBuilder()
.add("id", tech.getOrgUser().getId())
.add("name", tech.getOrgUser().getName()))
.add("Organization", Json.createObjectBuilder()
.add("id", tech.getOrganization().getId())
.add("name", tech.getOrganization().getName()))
.add("Product", Json.createObjectBuilder()
.add("id", tech.getProduct().getId())
.add("name", tech.getProduct().getName()))
.add("Certification", Json.createObjectBuilder()
.add("id", tech.getCertification().getId())
.add("name", tech.getCertification().getName()));
techArrBuilder.add(jsonObject);
}
JsonArray jsonArray = techArrBuilder.build();
Map<String, Object> prop = new HashMap<String, Object>() {
{
put(JsonGenerator.PRETTY_PRINTING, true);
}
};
JsonWriter jsonWriter = Json.createWriterFactory(prop).createWriter(System.out);
jsonWriter.writeArray(jsonArray);
jsonWriter.close();
The output should be:
[
{
"id":1,
"muMask":1,
"muAssignedMask":2,
"muAskedAssignedMask":3,
"muWillCertMask":4,
"muAskedWillCertMask":5,
"certType":"cert",
"applyDate":"2014-04-03",
"certDate":"2014-04-03",
"notes":"notes",
"OrgUser":{
"id":1,
"name":"orguser"
},
"Organization":{
"id":1,
"name":"organization"
},
"Product":{
"id":1,
"name":"product"
},
"Certification":{
"id":1,
"name":"certification"
}
},
{
"id":2,
"muMask":1,
"muAssignedMask":2,
"muAskedAssignedMask":3,
"muWillCertMask":4,
"muAskedWillCertMask":5,
"certType":"cert",
"applyDate":"2014-04-03",
"certDate":"2014-04-03",
"notes":"notes",
"OrgUser":{
"id":2,
"name":"orguser"
},
"Organization":{
"id":2,
"name":"organization"
},
"Product":{
"id":2,
"name":"product"
},
"Certification":{
"id":2,
"name":"certification"
}
},
{
"id":3,
"muMask":1,
"muAssignedMask":2,
"muAskedAssignedMask":3,
"muWillCertMask":4,
"muAskedWillCertMask":5,
"certType":"cert",
"applyDate":"2014-04-03",
"certDate":"2014-04-03",
"notes":"notes",
"OrgUser":{
"id":3,
"name":"orguser"
},
"Organization":{
"id":3,
"name":"organization"
},
"Product":{
"id":3,
"name":"product"
},
"Certification":{
"id":3,
"name":"certification"
}
}
]