problem with deserializing XML into instances of Java objects - java

So I have a Spring Boot main() that queries an API that returns some XML (CRed and indented for your viewing pleasure)
<ns1:Entities xmlns:ns1="https://my.company.com/rest/model">
<ns1:Entity name="Model" href="..512971">
<ns1:Attribute name="id" type="Number" value="512971"/>
<ns1:Attribute name="modelNumber" type="String" value="4857395960"/>
</ns1:Entity>
</ns1:Entities>
that I want to deserialize into instances of class Model
public class Model implements java.io.Serializable {
private static final long serialVersionUID = -1234L;
#Id
#Column(name="id")
private Long id;
#Column(name="model_number")
private String modelNumber;
//constructors
public Model() {}
public Model( Long id, String num) {
this.id = id;
this.modelNumber = num;
}
public Model( String idStr, String num) {
this.id = Long.getLong(idStr);
this.modelNumber = num;
}
//getters and setters
public Long getId() {
return id;
}
public void setId( Long id) {
this.id = id;
}
public void setId( String idStr) {
this.id = Long.getLong(idStr);
}
....
}
and
#JsonIgnoreProperties(ignoreUnknown=true)
#JacksonXmlRootElement(localName="Attribute", namespace="ns1")
public class Attribute implements java.io.Serializable {
private static final long serialVersionUID = -5678L;
public String name;
public String type;
public String value;
//constructors
public Entity() {}
public Entity( String name, String type, String value) {
this.name = name;
this.type = type;
this.value = value;
}
//getters and setters
.....
}
and
#JsonIgnoreProperties(ignoreUnknown=true)
#JacksonXmlRootElement(localName="Entity", namespace="ns1")
public class Entity implements java.io.Serializable {
private static final long serialVersionUID = -9876L;
public String name;
public String href;
#JacksonXmlProperty(localName="Attribute")
#JacksonXmlElementWrapper(useWrapping=false)
private List<Attribute> list_attribute = new LinkedList<Attribute>();
//constructors
public Entity() {}
public Entity( String name, String href, List<Attribute> lisst) {
this.name = name;
this.href = href;
this.list_attribute = lisst;
}
//getters and setters
....
}
and
#JsonIgnoreProperties(ignoreUnknown=true)
#JacksonXmlRootElement(localName="Entities", namespace="ns1")
public class Entities implements java.io.Serializable {
private static final long serialVersionUID = -2345L;
#JacksonXmlProperty(localName="Entity")
#JacksonXmlElementWrapper(useWrapping=false)
private List<Entity> list_entity = new LinkedList<Entity>();
//constructors
public Entities() {}
public Entities( List<Entity> lisst) {
this.list_entity = lisst;
}
//getters and setters
public List<Entity> getList_entity() {
return list_entity;
}
public void setList_entity( List<Entity> lisst) {
this.list_entity = lisst;
}
....
}
So at last we get to a chunk of main()
HttpHeaders headers = new HttpHeaders();
headers.add( HttpHeaders.ACCEPT, MediaType.APPLICATION_XML_VALUE);
HttpEntity<Object> reqquest = new HttpEntity<Object>( null, headers);
ResponseEntity<String> responnse = this.restTemplate.exchange( "https://myendpointgoeshere.com", HttpMethod.GET, reqquest, String.class, 0);
Entities entities_obj = this.xmlMapper.readValue( xmlStr, Entities.class);
List<Model> list_model = Model.deserialize( entities_obj); // <--
throws
IAE - fld:id - type: + Number - value:512971
java.lang.IllegalArgumentException: Can not set java.lang.Long field ...Model.id to null
and yet
Model model_0 = list_model.get[0];
System.out.println( model_0);
does show a correctly populated instance of Model. So this is all mostly right but not 100% right. What am I doing wrong/not doing right? And there will be many kinds of Entity, Model being only one so Model should extend Entity ?
TIA,
Still-learning Steve

Related

#Mapping annotation is not mapping correctly to convert Entity object to DTO object

I am using #Mapping to map my entity class to DTO class.All values are being mapped perfectly except one- hostPlayerId is coming null.
I am hitting my API below which is returning Lobby object and I am using MapStruct to map the Entity to the DTO. Its mapping every field except hostPlayerId field.
#GetMapping("/lobby/{id}")
#ResponseStatus(HttpStatus.OK)
#ResponseBody
public LobbyGetDTO getLobbyInfo(#RequestHeader("X-Auth-Token") String token, #PathVariable("id") long id) {
Lobby lobby = lobbyService.getLobby(id);
log.info("here here "+lobby.toString());
LobbyGetDTO lobbyInfoDTO = DTOMapper.INSTANCE.convertEntityToLobbyGetDTO(lobby);
log.info(lobbyInfoDTO.toString());
return lobbyInfoDTO;
}
The logger after hitting the API -
2020-04-18 00:00:01.738 INFO 18486 --- [nio-8080-exec-6] c.u.i.s.s.controller.LobbyController : here here Lobby{id=2, name='Test Lobby', hostPlayerId=1, playerIds=[], chatId=null, gameId=null, status=0}
2020-04-18 00:00:01.740 INFO 18486 --- [nio-8080-exec-6] c.u.i.s.s.controller.LobbyController : LobbyGetDTO{id=2, name='Test Lobby', hostPlayerId=null, playerIds=[], gameId=null}
Map Interface-
#Mapper
public interface DTOMapper {
DTOMapper INSTANCE = Mappers.getMapper(DTOMapper.class);
#Mapping(source = "id", target = "id")
#Mapping(source = "name", target = "name")
#Mapping(source = "gameId", target = "gameId")
#Mapping(source = "hostPlayerId", target = "hostPlayerId")
#Mapping(source = "playerIds", target = "playerIds")
LobbyGetDTO convertEntityToLobbyGetDTO(Lobby lobby);
}
mapping implementation method created during build phase-
#Override
public LobbyGetDTO convertEntityToLobbyGetDTO(Lobby lobby) {
if ( lobby == null ) {
return null;
}
LobbyGetDTO lobbyGetDTO = new LobbyGetDTO();
lobbyGetDTO.setGameId( lobby.getGameId() );
lobbyGetDTO.setName( lobby.getName() );
lobbyGetDTO.setId( lobby.getId() );
List<Long> list = lobby.getPlayerIds();
if ( list != null ) {
lobbyGetDTO.setPlayerIds( new ArrayList<Long>( list ) );
}
lobbyGetDTO.sethostPlayerId( lobby.gethostPlayerId() );
return lobbyGetDTO;
}
My DTO class
public class LobbyGetDTO {
private Long id;
private String name;
private Long hostPlayerId;
private List<Long> playerIds;
private Long gameId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long gethostPlayerId() {
return hostPlayerId;
}
public void sethostPlayerId(Long hostPlayerIdPlayerId) {
this.hostPlayerId = hostPlayerId;
}
public List<Long> getPlayerIds() {
return playerIds;
}
public void setPlayerIds(List<Long> playerIds) {
this.playerIds = playerIds;
}
public Long getGameId() {
return gameId;
}
public void setGameId(Long gameId) {
this.gameId = gameId;
}
}
My Entity class
#Entity
#Table(name = "LOBBY")
public class Lobby implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long id;
#Column(nullable = false)
private String name;
#Column(nullable = false)
private Long hostPlayerId;
}
I am unable to understand what am I missing here.
Maybe, getter and setter in the DTO need to be named as getHostPlayerId() / setHostPlayerId() so that the mapper could detect them.
Also, you do not assign any value in the setter because of typo in the argument:
public void sethostPlayerId(Long hostPlayerIdPlayerId) {
this.hostPlayerId = hostPlayerId;
}
should be:
public void setHostPlayerId(Long hostPlayerId) {
this.hostPlayerId = hostPlayerId;
}

Spring boot+jersey api+ JPA : failed to lazily initialize a collection of role

I am new with using spring boot + jersey api + JPA.
I hava three entity that uses one to many bidirectional mapping. When i used spring boot + jersey api+ JPA I get error :
failed to lazily initialize a collection of role: com.kavinaam.GSTbilling.entity.Country.states, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.kavinaam.GSTbilling.entity.City["states"]->com.kavinaam.GSTbilling.entity.States["countyId"]->com.kavinaam.GSTbilling.entity.Country["states"])
I have added my entity, dao , services and end point.
#Entity
#Table(name="country")
public class Country implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id")
private int id;
#Column(name="countryName")
private String countryName;
#OneToMany(mappedBy = "countyId",cascade = CascadeType.ALL)
private Set<States> states;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
public Set<States> getStates() {
return states;
}
public void setStates(Set<States> states) {
this.states = states;
}
}
My state class:
#Entity
#Table(name="states")
public class States implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id")
private int id;
#ManyToOne
#JoinColumn(name="countyId")
private Country countyId;
#Column(name="stateName")
private String stateName;
#OneToMany(mappedBy = "states", cascade = CascadeType.ALL)
private Set<City> city;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Country getCountyId() {
return countyId;
}
public void setCountyId(Country countyId) {
this.countyId = countyId;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
public Set<City> getCity() {
return city;
}
public void setCity(Set<City> city) {
this.city = city;
}
}
My city class:
#Entity
#Table(name="cities")
public class City implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id")
private int id;
#ManyToOne
#JoinColumn(name="stateId")
private States states;
#Column(name="cityName")
private String cityName;
#Column(name="zip")
private String zip;
public void setId(int id) {
this.id = id;
}
public void setZip(String zip) {
this.zip = zip;
}
public States getStates() {
return states;
}
public void setStates(States states) {
this.states = states;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public String getZip() {
return zip;
}
public int getId() {
return id;
}
}
My DAO:
#Transactional
#Repository
public class GSTCityDAO implements IGSTCityDAO {
#PersistenceContext
private EntityManager entityManager;
//#SuppressWarnings("unchecked")
#Override
public List<City> getAllCities() {
//Session session = sessionFactory.getCurrentSession();
String hql = "FROM City as ct ORDER BY ct.id";
List<City> l = entityManager.createQuery(hql,City.class).getResultList();
return l;
}
#Override
public City getCityById(int cityId) {
return entityManager.find(City.class, cityId);
}
#SuppressWarnings("unchecked")
#Override
public List<City> getCityByStateId(States stateId) {
String getcitybystate = " FROM City as c WHERE c.states = ?";
return (List<City>) entityManager.createQuery(getcitybystate).setParameter(1, stateId).getResultList();
}
#Override
public void addCity(City city) {
entityManager.persist(city);
}
#Override
public void updateCity(City city) {
City cityctl = getCityById(city.getId());
cityctl.setCityName(city.getCityName());
cityctl.setZip(city.getZip());
cityctl.setStates(city.getStates());
entityManager.flush();
}
#Override
public void deleteCity(int cityId) {
entityManager.remove(getCityById(cityId));
}
#Override
public boolean cityExists(String name, String zip) {
String hql = "FROM City WHERE cityName = ? and zip = ?";
int count = entityManager.createQuery(hql).setParameter(1,name).setParameter(2, zip).getResultList().size();
return count > 0 ? true : false;
}
}
Services:
#Service
public class GSTCityService implements IGSTCityService {
#Autowired
private IGSTCityDAO cityDAO;
#Override
public List<City> getAllCities() {
List<City> l = cityDAO.getAllCities();
Hibernate.initialize(l);
return l;
}
public List<City> getCityByStateId(States stateId) {
return cityDAO.getCityByStateId(stateId);
}
#Override
public City getCityById(int cityId) {
City city = cityDAO.getCityById(cityId);
return city;
}
#Override
public synchronized boolean addCity(City city) {
if(cityDAO.cityExists(city.getCityName(), city.getZip())){
return false;
}else{
cityDAO.addCity(city);
return true;
}
}
#Override
public void updateCity(City city) {
cityDAO.updateCity(city);
}
#Override
public void deleteCity(int cityId) {
cityDAO.deleteCity(cityId);
}
}
End Point:
#Component
#Path("/")
public class Test {
private static final Logger logger = LoggerFactory.getLogger(Test.class);
#Autowired
private IGSTCityService cityService;
#GET
#Path("/hi")
#Produces(MediaType.APPLICATION_JSON)
public Response hello(){
return Response.ok("Hello GST").build();
}
#GET
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
public Response getAllDate(){
List<City> list = cityService.getAllCities();
for(City city: list){
System.out.println(city);
}
return Response.ok(list).build();
}
#GET
#Path("/test/{id}")
#Produces(MediaType.APPLICATION_JSON)
public Response getAllDateBySome(#PathParam("id") Integer id){
States state = new States();
state.setId(id);
List<City> list = cityService.getCityByStateId(state);
return Response.ok(list).build();
}
#GET
#Path("/{id}")
#Produces(MediaType.APPLICATION_JSON)
public Response getDataById(#PathParam("id")Integer id){
City citl = cityService.getCityById(id);
return Response.ok(citl).build();
}
#POST
#Path("/add")
#Consumes(MediaType.APPLICATION_JSON)
public Response addData(City city){
boolean isAdded = cityService.addCity(city);
if(!isAdded){
return Response.status(Status.CONFLICT).build();
}
return Response.created(URI.create("/gst/"+ city.getId())).build();
}
#PUT
#Path("/update")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response updateCountry(City city){
cityService.updateCity(city);
return Response.ok(city).build();
}
#DELETE
#Path("/{id}")
#Consumes(MediaType.APPLICATION_JSON)
public Response deleteCountry(#PathParam("id")Integer id){
cityService.deleteCity(id);
return Response.noContent().build();
}
}
I am using import org.springframework.transaction.annotation.Transactional; for transnational in DAO. Also I can not use #PersistenceContext(type=PersistenceContextType.EXTENDED) and fetch type Eager because I get error of Maximum stack size exceeded
I solved it by using the #JsonBackReference on OneToMany relationship. The problem is with the Serialization and Deserialization.
" the property annotated with #JsonManagedReference annotation is handled normally (serialized normally, no special handling for deserialization) and the property annotated with #JsonBackReference annotation is not serialized; and during deserialization, its value is set to instance that has the "managed" (forward) link."
You should do one or both of the following:
1) Move the #Transactional from DAO to Service. Thats a good idea in general as usually are still processing the result entities in some way on that layer.
2) Fetch the dependencies in the queries explicitly:
select ct FROM City as ct inner join fetch ct.states s ORDER BY ct.id

java.lang.IllegalArgumentException: JSON object doesn't have the primary key field 'id'

I use realm to parse this JSON, but I get this error:
java.lang.IllegalArgumentException: JSON object doesn't have the primary key field 'id'.
LINK of Json
this is my method :
Realm r = Realm.getDefaultInstance();
r.beginTransaction();
r.createOrUpdateObjectFromJson(Application.class,result);
r.commitTransaction();
my Application class is :
public class Application extends RealmObject {
#PrimaryKey
private int id;
private RealmList<girl> girls;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public RealmList<girl> getGirls() {
return girls;
}
public void setGirls(RealmList<girl> girls) {
this.girls = girls;
}
public Application() {
}
public Application(int id, RealmList<girl> girls) {
this.id = id;
this.girls = girls;
}
}
my class girl is
public class girl extends RealmObject {
#PrimaryKey
private int id;
private String name;
private String ville;
private String tel;
private String photo;
//getters and setters and constructors with and without params
}
try to use realm.copyFromRealm(); and for more refer bellow link
https://github.com/realm/realm-java/issues/1973

Hibernate entity classes getters returning null after setting value

I have a hibernate entity class
public class MyComplexClass implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
String name;
int number;
#ElementCollection
Map<String,String> myMap;
#ManyToOne
Simple simple;
public MyComplexClass(String name, int number, Map<String,String> myMap) {
this.name = name;
this.port = number;
this.myMap = myMap;
}
public MyComplexClass() {
// TODO Auto-generated constructor stub
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setNumber(int number) {
this.port = number;
}
public int getPort() {
return port;
}
public void setMyMap(Map<String,String> myMap) {
this.myMap = myMap;
}
public Map<String,String> getMyMap() {
return this.myMap;
}
public Simple getSimple() {
return this.simple;
}
And in the class simple I have a mapping of the form
#Entity
#Table(name = "Simple")
public class Simple implements Comparable<Simple>, Serializable {
#JsonProperty
#OneToMany(mappedBy="simple",fetch = FetchType.EAGER,cascade = CascadeType.ALL)
List<MyComplexClass> myComplexClass;
public void setMyComplexClass(List<MyComplexClass> myComplexClass) {
this.myComplexClass = myComplexClass;
}
public List<MyComplexClass> getMyComplexClass() {
return this.myComplexClass;
}
Somewhere in the system I set the values as
Map<String, String> myMap = new HashMap<String,String>();
myMap.put("value","value");
MyComplexClass myComplexClass = new MyComplexclass("a", 123, myMap)
List<MyComplexClass> myComplexClassList = new ArrayList<MyComplexClass>();
myComplexClassList.add(myComplexClassList)
simple.setMyComplexClass(myComplexClassList);
// save to the database
dao.save(simple);
But when I get the value as
Simple simple = dao.getSimple(simple.id);
`simple.getMyComplexClass.get(0).getMyMap.get("value")`
. It returns a null pointer . When I debug I see that the simple.getMyComplexClass() is null itself
Why isn't it returning the values set? Is it related to the database or in memory cache?
In the database I do see a null in the foreign key column of the MyComplex class table, is this the reason?

how to return values selected by hibernate query in json form?

my question here is how do i return values selected from hibernate query in the json form.
BankController.java
#RequestMapping(value = "/getohlcall", method = RequestMethod.POST)
public #ResponseBody List<Trading_Data> getOhlcAll(#RequestBody OhlcRequest ohlcRequest) {
List<Trading_Data> list;
list = bankServices.getOhlc(ohlcRequest);
return list;
}
My DAO implementation class which for now returns four values.
BankDaoImpl.java
public List<Trading_Data> getOhlc(OhlcRequest ohlcRequest){
sessionFactory.openSession();
session=sessionFactory.openSession();
Criteria cr = session.createCriteria(Trading_Data.class)
.setProjection(Projections.projectionList()
.add(Projections.property("minPrice"), "minPrice")
.add(Projections.property("maxPrice"), "maxPrice")
.add(Projections.property("closingPrice"), "closingPrice")
.add(Projections.property("prevClosing"), "prevClosing"))
.setResultTransformer(Transformers.aliasToBean(Trading_Data.class));
List<Trading_Data> list = cr.list();
return list;
}
My entity class which is mapped with my table in database.
Trading_Data.java
public class Trading_Data {
#Entity
#Table
#JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Trading_Data {
#Id
#Column
#JsonView(View.Summary.class)
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column
#JsonView(View.Summary.class)
private String stockCode;
#Column
private long maxPrice;
#Column
private long minPrice;
#Column
private long closingPrice;
#Column
private long prevClosing;
#Column
#JsonView(View.Summary.class)
private String eDate;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getStockCode() {
return stockCode;
}
public void setStockCode(String stockCode) {
this.stockCode = stockCode;
}
public long getMaxPrice() {
return maxPrice;
}
public void setMaxPrice(long maxPrice) {
this.maxPrice = maxPrice;
}
public long getMinPrice() {
return minPrice;
}
public void setMinPrice(long minPrice) {
this.minPrice = minPrice;
}
public long getClosingPrice() {
return closingPrice;
}
public void setClosingPrice(long closingPrice) {
this.closingPrice = closingPrice;
}
public long getPrevClosing() {
return prevClosing;
}
public void setPrevClosing(long prevClosing) {
this.prevClosing = prevClosing;
}
public String geteDate() {
return eDate;
}
public void seteDate(String eDate) {
this.eDate = eDate;
}
}
Json data i am currently getting is
[
{
"id": 0,
"maxPrice": 54,
"minPrice": 58,
"closingPrice": 45,
"prevClosing": 215
}
]
as you can see i don't want id for this api but i might want for some other api.
My questions are:-
is there no way for eg. returning only those values(in json format) which are selected by hibernate query ?
for e.g i created one pojo class which has four properties (maxprice, minprice, prevclosing,closingprice). can i map this pojo class with values returned by hibernate query and return to the client in json format?
Try to use 'produces' in your resource method. Like this :
#RequestMapping(value = "/getohlcall", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody List<Trading_Data> getOhlcAll(#RequestBody OhlcRequest ohlcRequest) {
List<Trading_Data> list;
list = bankServices.getOhlc(ohlcRequest);
return list;
}

Categories