I have this problem in the back end when I post a data form from angular please someone help me I trie to solve this problem by object mapper but I don't understand well how can I do it correctly
the error is :
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of entity.Group (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{
"idGrp": 2,
"nomGroup": "intranet"
}'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of entity.Group (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{
"idGrp": 2,
"nomGroup": "intranet"
}')
at [Source: (PushbackInputStream); line: 1, column: 236] (through reference chain: entity.Employe["group"])]*
this is my class Group
package entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="groups")
public class Group implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long idGrp;
private String NomGroup;
public Group()
{
}
public Group(Long id, String nomGroup) {
super();
this.idGrp = id;
NomGroup = nomGroup;
}
}
Im trying to post a data of employee which contain the data of entity group
class employee
package entity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
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.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.GenericGenerator;
#Entity
public class Employe implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "myid")
#GenericGenerator(name = "myid", strategy = "entity.MyGenerator")
private Integer matricule;
private String nom;
private String prenom ;
private String nom_ar;
private String prenom_ar;
private int age;
private String description;
private String email;
private int codeP;
private int numTele;
private String adresse;
private String ville;
#JoinColumn(name="idGrp")
#ManyToOne(cascade = {CascadeType.ALL})
Group group;
public Employe(Integer matricule, String nom, String prenom, String nom_ar, String prenom_ar, int age,
String description, String email, int codeP, int numTele, String adresse, String ville, Group group) {
super();
this.matricule = matricule;
this.nom = nom;
this.prenom = prenom;
this.nom_ar = nom_ar;
this.prenom_ar = prenom_ar;
this.age = age;
this.description = description;
this.email = email;
this.codeP = codeP;
this.numTele = numTele;
this.adresse = adresse;
this.ville = ville;
}
public Employe(Integer matricule, String nom, String prenom, String nom_ar, String prenom_ar, int age,
String description, String email, int codeP, int numTele, String adresse, String ville) {
this.matricule = matricule;
this.nom = nom;
this.prenom = prenom;
this.nom_ar = nom_ar;
this.prenom_ar = prenom_ar;
this.age = age;
this.description = description;
this.email = email;
this.codeP = codeP;
this.numTele = numTele;
this.adresse = adresse;
this.ville = ville;
}
}
controller
#CrossOrigin(origins = "http://localhost:4200")
#PostMapping("addEmp")
public ResponseEntity<Employe> addEmp(#RequestBody Employe ep) throws JsonProcessingException
{
Employe p=this.servEmp.addEmp(ep);
return new ResponseEntity<>(p, HttpStatus.CREATED);
}
please help me how can I convert the json data to object I spend now two days In this error
I try to use commandRunner
#Bean
public CommandLineRunner run(ServiceEmp ServiceEmp) {
return args->{
Employe e=new Employe(0,"","","","",0,"","",0,0,"","");
ObjectMapper objectMapper=new ObjectMapper();
TypeReference<Employe> TypeReference =new TypeReference<Employe>() {};
InputStream InputStream=TypeReference.class.getResourceAsStream(objectMapper.writeValueAsString(ServiceEmp.addEmp(e)));
try {
e=objectMapper.readValue(InputStream,TypeReference);
ServiceEmp.addEmp(e);
System.out.print("saved");
}
catch(IOException a)
{
System.out.print("not saved"+a.getMessage());
}
output:
**Employe [nom=, prenom=, nom_ar=, prenom_ar=, matricule=0, age=0, description=, email=, codeP=0, numTele=0, adresse=, ville=]
[2m2021-09-25 20:40:39.966[0;39m [32m INFO[0;39m [35m10044[0;39m [2m---[0;39m [2m[ main][0;39m [36mConditionEvaluationReportLoggingListener[0;39m [2m:[0;39m
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
[2m2021-09-25 20:40:39.992[0;39m [31mERROR[0;39m [35m10044[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.s.boot.SpringApplication [0;39m [2m:[0;39m Application run failed
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:794) ~[spring-boot-2.5.4.jar:2.5.4]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:775) ~[spring-boot-2.5.4.jar:2.5.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:345) ~[spring-boot-2.5.4.jar:2.5.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-2.5.4.jar:2.5.4]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) ~[spring-boot-2.5.4.jar:2.5.4]
at cni.tn.CniApp.CniAppApplication.main(CniAppApplication.java:34) ~[classes/:na]
Caused by: java.lang.IllegalArgumentException: argument "src" is null
at com.fasterxml.jackson.databind.ObjectMapper._assertNotNull(ObjectMapper.java:4693) ~[jackson-databind-2.11.1.jar:2.11.1]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3478) ~[jackson-databind-2.11.1.jar:2.11.1]
at cni.tn.CniApp.CniAppApplication.lambda$0(CniAppApplication.java:46) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:791) ~[spring-boot-2.5.4.jar:2.5.4]
... 5 common frames omitted**
The problem is the usage of constructors with parameters. Jackson can't map this by default. I think, there are two options:
Add the default constructor and all required getters and setters.
Add #JsonCreator to your paramized constructor.
For example:
public class Bean {
public int id;
public String name;
#JsonCreator
public Bean(
#JsonProperty("id") int id,
#JsonProperty("theName") String name) {
this.id = id;
this.name = name;
}
}
I am not sure, if you really need #JsonProperty for the parameters of the constructor, if you are using spring boot!
Related
Trying to save an object of type "Salary" which has ManyToOne relationships with "Role", "City", "SalarySite". It appears to be printing correctly with all the expected data but saving fails. Other similar questions all seem to be missing "#Autowired" but it is present in mine.
The "Dataloader" class, runs a "GoogleSearchScraper" class where we see the error.
City
package fyi.incomeoutcome.salarytaxspend.city;
import fyi.incomeoutcome.salarytaxspend.salary.Salary;
import javax.persistence.*;
import java.util.Set;
#Entity
public class City {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String name;
private String country;
private String currency;
#OneToMany(mappedBy="city", cascade = CascadeType.ALL)
private Set<Salary> salaries;
protected City(){}
public City(String name, String country, String currency){
this.name = name;
this.country = country;
this.currency = currency;
}
public String getName(){ return this.name; }
public String getCountry(){ return this.country; }
public String toString(){
return String.format("City[id=%d, name='%s', country = '%s', currency= '%s']",
id, name, country, currency);
}
}
City Repository
package fyi.incomeoutcome.salarytaxspend.city;
import org.springframework.stereotype.Repository;
import org.springframework.data.repository.CrudRepository;
#Repository
public interface CityRepository extends CrudRepository<City, Long> {
}
Role
package fyi.incomeoutcome.salarytaxspend.role;
import fyi.incomeoutcome.salarytaxspend.salary.Salary;
import javax.persistence.*;
import java.util.Set;
#Entity
public class Role {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String seniority;
private String roleName;
#OneToMany(mappedBy="role", cascade = CascadeType.ALL)
private Set<Salary> salaries;
protected Role(){}
public Role(String seniority,String roleName){
this.seniority = seniority;
this.roleName = roleName;
}
public String getSeniorityAndRole(){
if (this.seniority != ""){
return String.format("%s %s", this.seniority, this.roleName);
} else{
return roleName;
}
}
public String toString(){
return String.format("id=%d, %s %s", id, seniority, roleName);
}
}
Role Repository
package fyi.incomeoutcome.salarytaxspend.role;
import org.springframework.stereotype.Repository;
import org.springframework.data.repository.CrudRepository;
#Repository
public interface RoleRepository extends CrudRepository<Role, Long> {
}
SalarySite
package fyi.incomeoutcome.salarytaxspend.salary.salarysite;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class SalarySite {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String name;
private String searchUrl;
private String salaryElementClass;
protected SalarySite(){}
public SalarySite(String name, String searchUrl, String salaryElementClass){
this.name = name;
this.searchUrl = searchUrl;
this.salaryElementClass = salaryElementClass;
}
public String getName() {
return name;
}
public String toString(){
return String.format("%s %s %s", name, searchUrl, salaryElementClass);
}
public String getSearchUrl(){
return searchUrl;
}
public String getSalaryElementClass(){
return salaryElementClass;
}
}
SalarySiteRepo
package fyi.incomeoutcome.salarytaxspend.salary.salarysite;
import org.springframework.stereotype.Repository;
import org.springframework.data.repository.CrudRepository;
#Repository
public interface SalarySiteRepository extends CrudRepository<SalarySite, Long> {
}
Salary
package fyi.incomeoutcome.salarytaxspend.salary;
import fyi.incomeoutcome.salarytaxspend.city.City;
import fyi.incomeoutcome.salarytaxspend.role.Role;
import fyi.incomeoutcome.salarytaxspend.salary.salarysite.SalarySite;
import javax.persistence.*;
#Entity
public class Salary {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private int compensation;
#ManyToOne(optional = false)
#JoinColumn(name = "role_id")
private Role role;
#ManyToOne(optional = false)
#JoinColumn(name = "city_id")
private City city;
#ManyToOne(optional = false)
#JoinColumn(name = "site_id")
private SalarySite site;
protected Salary(){}
public Salary(int compensation, Role role, City city, SalarySite site){
this.compensation = compensation;
this.role = role;
this.city = city;
this.site = site;
}
public int getCompensation(){
return this.compensation;
}
public String getCity(){
return city.getName();
}
public String getSeniorityAndRoleName(){
return role.getSeniorityAndRole();
}
public String toString(){
return String.format("Salary[id=%d, compensation=%d, city='%s', role='%s'",
id, compensation, city, role);
}
}
Salary Repository
import fyi.incomeoutcome.salarytaxspend.city.City;
import fyi.incomeoutcome.salarytaxspend.role.Role;
import fyi.incomeoutcome.salarytaxspend.salary.salarysite.SalarySite;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface SalaryRepository extends CrudRepository<Salary, Long> {
//List<Salary> findByLocation(String location);
Salary findById(long id);
boolean existsBySiteAndCityAndRole(SalarySite salarySite, City city, Role role);
}
Dataloader
package fyi.incomeoutcome.salarytaxspend.salary.service;
import fyi.incomeoutcome.salarytaxspend.city.City;
import fyi.incomeoutcome.salarytaxspend.city.CityRepository;
import fyi.incomeoutcome.salarytaxspend.role.RoleRepository;
import fyi.incomeoutcome.salarytaxspend.salary.Salary;
import fyi.incomeoutcome.salarytaxspend.salary.SalaryRepository;
import fyi.incomeoutcome.salarytaxspend.salary.salarysite.SalarySite;
import fyi.incomeoutcome.salarytaxspend.role.Role;
import fyi.incomeoutcome.salarytaxspend.salary.salarysite.SalarySiteRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
#Component
#Slf4j
public class DataLoader {
#Autowired
private SalaryRepository salaryRepository;
#Autowired
private SalarySiteRepository siteRepository;
#Autowired
private CityRepository cityRepository;
#Autowired
private RoleRepository roleRepository;
#PostConstruct
public void process() {
List<SalarySite> salarySiteList = new ArrayList<>();
siteRepository.findAll().forEach(salarySiteList::add);
List<Role> roleList = new ArrayList<>();
roleRepository.findAll().forEach(roleList::add);
List<City> cityList = new ArrayList();
cityRepository.findAll().forEach(cityList::add);
List<Salary> salaryList = new ArrayList<>();
salaryRepository.findAll().forEach(salaryList::add);
log.info("Entering Loop");
log.info("--------------------");
int numberOfSalaries = salaryList.size();
int numberOfRoles = roleList.size();
int numberOfSites = salarySiteList.size();
int numberOfCities = cityList.size();
log.info(String.format("salary list %d", numberOfSalaries));
log.info(String.format("role list %d", numberOfRoles));
log.info(String.format("site list %d", numberOfSites));
log.info(String.format("city list %d", numberOfCities));
for (SalarySite salarySite : salarySiteList){
for (City city: cityList){
for (Role role: roleList){
boolean foundSalary = salaryRepository.existsBySiteAndCityAndRole(salarySite, city, role);
if (foundSalary == true) {
log.debug("Found");
} else {
log.debug("Not Found, Scraping");
String roleTitle = role.getSeniorityAndRole();
String cityName = city.getName();
String searchUrl = salarySite.getSearchUrl();
String salaryElementClass = salarySite.getSalaryElementClass();
ScraperService siteScraper = new GoogleSearchScraper(role, city, salarySite);
siteScraper.executeScrape();
}
}
}
}
}
}
Google Search Scraper
package fyi.incomeoutcome.salarytaxspend.salary.service;
import fyi.incomeoutcome.salarytaxspend.city.City;
import fyi.incomeoutcome.salarytaxspend.role.Role;
import fyi.incomeoutcome.salarytaxspend.salary.Salary;
import fyi.incomeoutcome.salarytaxspend.salary.SalaryRepository;
import fyi.incomeoutcome.salarytaxspend.salary.salarysite.SalarySite;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
#Component
#Slf4j
public class GoogleSearchScraper implements ScraperService {
private Role role;
private City city;
private SalarySite site;
private String webPageUrl;
private int compensation;
#Autowired
SalaryRepository salaryRepo;
public GoogleSearchScraper(){}
public GoogleSearchScraper(Role role, City city, SalarySite site){
this.role = role;
this.city = city;
this.site = site;
}
#Override
public void executeScrape(){
int statusCodeFetchUrl = fetchWebpageUrl();
log.info(String.format("fetchWebPageUrl for %s : %d", toString(), statusCodeFetchUrl));
int parsePageStatusCode = parsePageForSalary();
log.info(String.format("parseUrl for salary %s : %d", toString(), parsePageStatusCode));
saveSalary();
}
#Override
public int fetchWebpageUrl(){
String title = role.getSeniorityAndRole();
title = title.replace(" ", "+");
String searchUrl = site.getSearchUrl();
String cityName = city.getName();;
String fullUrl = String.format("%s%s+%s", searchUrl, title, cityName);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(fullUrl))
.GET()
.build();
int statusCode = 0;
try{
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
statusCode = response.statusCode();
String jsonResultLink = new JSONObject(response.body())
.getJSONArray("items")
.getJSONObject(0)
.getString("link");
log.info(city + " " + role + " " + jsonResultLink);
this.webPageUrl = jsonResultLink;
return statusCode;
} catch(Exception e) {
log.error(e.toString());
return statusCode;
}
}
#Override
public int parsePageForSalary() {
HttpClient client = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.ALWAYS)
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(this.webPageUrl))
.GET()
.build();
int statusCode = 0;
try{
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
statusCode = response.statusCode();
Document doc = Jsoup.parse(response.body());
Element salaryElement = doc.getElementsByClass(site.getSalaryElementClass()).first();
String salaryText = salaryElement.text();
char[] salaryChars = salaryText.toCharArray();
String nonDigitCharacters = "";
for (char c: salaryChars){
if (!Character.isDigit(c)){
salaryText = salaryText.replace(Character.toString(c),"");
nonDigitCharacters += c;
}
}
log.info(this.toString() + " removed " + nonDigitCharacters + " from salary " + salaryText);
this.compensation = Integer.parseInt(salaryText);
return statusCode;
} catch (Exception e){
log.error(e.toString());
return statusCode;
}
}
public void saveSalary(){
Salary scrapedSalary = new Salary(this.compensation, this.role, this.city, this.site);
log.info("saving " + scrapedSalary.toString());
salaryRepo.save(scrapedSalary);
}
#Override
public String getWebPageUrl() {
return webPageUrl;
}
#Override
public int getSalary() {
if (this.compensation == 0){
parsePageForSalary();
return this.compensation;
}
return this.compensation;
}
public String toString(){
return String.format("Scraper %s, %s, %s", role.getSeniorityAndRole(),
city.getName(), site.getName());
}
}
Error
2022-01-23 10:53:54.194 INFO 34291 --- [ main] f.i.s.s.service.GoogleSearchScraper : saving Salary[id=0, compensation=36149, city='City[id=1, name='Dublin', country = 'Ireland', currency= 'EUR']', role='id=1, Junior Software Developer'
2022-01-23 10:53:54.194 WARN 34291 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataLoader': Invocation of init method failed; nested exception is java.lang.NullPointerException
2022-01-23 10:53:54.195 INFO 34291 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2022-01-23 10:53:54.196 INFO 34291 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2022-01-23 10:53:54.210 INFO 34291 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
2022-01-23 10:53:54.211 INFO 34291 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2022-01-23 10:53:54.222 INFO 34291 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-01-23 10:53:54.237 ERROR 34291 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataLoader': Invocation of init method failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:440) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.14.jar:5.3.14]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.14.jar:5.3.14]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.2.jar:2.6.2]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[spring-boot-2.6.2.jar:2.6.2]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) ~[spring-boot-2.6.2.jar:2.6.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) ~[spring-boot-2.6.2.jar:2.6.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.2.jar:2.6.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) ~[spring-boot-2.6.2.jar:2.6.2]
at fyi.incomeoutcome.salarytaxspend.SalaryTaxSpendApplication.main(SalaryTaxSpendApplication.java:27) ~[classes/:na]
Caused by: java.lang.NullPointerException: null
at fyi.incomeoutcome.salarytaxspend.salary.service.GoogleSearchScraper.saveSalary(GoogleSearchScraper.java:119) ~[classes/:na]
at fyi.incomeoutcome.salarytaxspend.salary.service.GoogleSearchScraper.executeScrape(GoogleSearchScraper.java:48) ~[classes/:na]
at fyi.incomeoutcome.salarytaxspend.salary.service.DataLoader.process(DataLoader.java:78) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) ~[spring-beans-5.3.14.jar:5.3.14]
... 18 common frames omitted
Since you are creating an instance of GoogleSearchScraper yourself, fields will not be autowired by Spring. Therefore, salaryRepository is null.
You could inject the SalaryRepository instance yourself upon creation of GoogleSearchScraper like this:
ScraperService siteScraper = new GoogleSearchScraper(role, city, salarySite, salaryRepo);
siteScraper.executeScrape();
Of course you need to add SalaryRepository to the constructor parameter list and assign it.
Consider removing #Component from GoogleSearchScraper if you want to create instances yourself. You only need it when instances shall be managed by Spring.
I am new to spring-data, I have this error java.lang.String cannot be cast to com.example.accessingdatamysql.User and do not know how to fix it! I add the various relevant parts of my code.
The method should output the oldest entry (via timestamp) by name.
Main.Controller
package com.example.accessingdatamysql;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
#RequestMapping(path="/demo")
public class MainController {
#Autowired
private UserRepository userRepository;
#Transactional
#PostMapping(path="/add")
public #ResponseBody String addNewUser (#RequestParam String name,
#RequestParam String email,#RequestParam String surname)
{
User n = new User();
n.setName(name);
n.setSurname(surname);
n.setEmail(email);
userRepository.create(n);
return "Saved";
}
#GetMapping(path="first")
User one(#RequestParam String name) {
return userRepository.findFirstByName(name);
}
}
User.java
package com.example.accessingdatamysql;
import java.sql.Timestamp;
import java.time.Instant;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
public String name;
private String email;
private String surname;
#Column(name="stmp", columnDefinition = "TIMESTAMP (6)")
Timestamp timestamp = Timestamp.from(Instant.now());
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
public Timestamp getTimestamp() {
return timestamp;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
RepoImpl.java
package com.example.accessingdatamysql;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.springframework.stereotype.Component;
#Component
public class UserRepositoryImpl implements UserRepository {
private final EntityManager em;
public UserRepositoryImpl(EntityManager entityManager) {
this.em = entityManager;
}
#Override
public User findFirstByName(String name) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<User> criteria = builder.createQuery(User.class);
Root<User> root = criteria.from(User.class);
criteria.select(root.get("name"));
criteria.orderBy(builder.asc(root.get("timestamp")));
TypedQuery<User> query = em.createQuery(criteria).setMaxResults(1);
return query.getSingleResult();
}
#Override
// per la creazione//
public void create(User entity) {
em.persist(entity);
}
}
ERROR
[Request processing failed; nested exception is java.lang.ClassCastException: java.lang.String cannot be cast to com.example.accessingdatamysql.User] with root cause
java.lang.ClassCastException: java.lang.String cannot be cast to com.example.accessingdatamysql.User
at com.example.accessingdatamysql.UserRepositoryImpl.findFirstByName(UserRepositoryImpl.java:35) ~[classes!/:0.0.1-SNAPSHOT]
If you meant to find User by name, you should have set the filter parameter not in criteria.select but in criteria.where:
public User findFirstByName(String name) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<User> criteria = builder.createQuery(User.class);
Root<User> root = criteria.from(User.class); // root is User
criteria.select(root).where(builder.equal(root.get("name"), name));
criteria.orderBy(builder.asc(root.get("timestamp")));
TypedQuery<User> query = em.createQuery(criteria).setMaxResults(1);
return query.getSingleResult();
}
While criteria.select(root.get("name")); implies that only column "name" is selected and returned, that is the name of the first user should be returned.
If such information is needed, it may be retrieved in the following way:
public String findFirstUserName() {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<String> criteria = builder.createQuery(String.class);
Root<User> root = criteria.from(User.class); // root is User
criteria.select(root.get("name")); // getting name
criteria.orderBy(builder.asc(root.get("timestamp"))); // of the first/earliest user
TypedQuery<String> query = em.createQuery(criteria).setMaxResults(1);
return query.getSingleResult();
}
Do just like the error says -
CriteriaQuery<String> criteria = builder.createQuery(String.class);
instead of
CriteriaQuery<User> criteria = builder.createQuery(User.class);
Read more here Reference
My application seems to work ok if I have 2 records or less in my database, but if I add more data then I got this warning in maven and error in the response:
2019-03-02 21:36:44.642 WARN 14734 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: 503 Service Temporarily Unavailable; nested exception is com.fasterxml.jackson.databind.JsonMappingException: 503 Service Temporarily Unavailable (through reference chain: java.util.ArrayList[2])]
It's actually quite strange, I receive the data and I'm able to output it in a string for instance, but if I return the list then crashes in execution.
My code:
package com.awesome2048.score;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
#RestController
public class ScoreController {
#Autowired
ScoreRepository repository;
#GetMapping("/scores")
public List<Score> fetchScores() throws JsonProcessingException {
List<Score> scores = (List<Score>) repository.findAll();
return scores;
}
}
The entity Score:
package com.awesome2048.score;
import javax.persistence.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.web.client.RestTemplate;
#JsonSerialize(using = ScoreSerializer.class)
#Entity
#Table(name = "scores")
public class Score {
private static final long serialVersionUID = -3009157732242241606L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "score", nullable = false)
private int score;
#Column(name = "ip", nullable = false)
private String ip;
public Score(String name, int score) {
this.name = name;
this.score = score;
}
public Score() {}
public String getName() {
return this.name;
}
public int getScore() {
return this.score;
}
public String getIp() {
return this.ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getCountryCode() {
String endpoint = "http://api.ipinfodb.com/v3/ip-country/?key=62ee2a10303261af0cf55d6eb2c807c8db5e6fa539fe5ba843c341f4062bfaea&ip= " + this.getIp();
RestTemplate restTemplate = new RestTemplate();
String countryCode = restTemplate.getForObject(endpoint, String.class).split(";")[3];
return countryCode;
}
}
I also implemented a custom serializer:
package com.awesome2048.score;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
public class ScoreSerializer extends StdSerializer<Score> {
public ScoreSerializer() {
this(null);
}
public ScoreSerializer(Class<Score> t) {
super(t);
}
#Override
public void serialize(Score score, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("name", score.getName());
jsonGenerator.writeNumberField("score", score.getScore());
jsonGenerator.writeStringField("countryCode", score.getCountryCode());
jsonGenerator.writeEndObject();
}
}
The reason is your get method:
public String getCountryCode() {
String endpoint = "http://api.ipinfodb.com/v3/ip-country/?key=62ee2a10303261af0cf55d6eb2c807c8db5e6fa539fe5ba843c341f4062bfaea&ip= " + this.getIp();
RestTemplate restTemplate = new RestTemplate();
String countryCode = restTemplate.getForObject(endpoint, String.class).split(";")[3];
return countryCode;
}
You are using ipinfodb API which has limitation. Info from their page:
To remain the stabilities of free service, a rate limit of 2 queries
per second applied to our API servers. Any IP querying the API
faster than this rate will temporarily blocked by our firewall. Your
IP will permanently banned if your keep hitting the API server by
ignoring this rate limit.
getter like this is a classical example of side effect in programming. You can not invoke other services, write data on disk in POJO methods which are designed to get/set variable. Instead, try to create batch job which will scan scores table and update required information. This implementation should take care about server limitation 2 requests per second.
I was trying to make a crud app which has two model objects of type Muscle and Exercise. Basically One Muscle Object can have a list of Exercise objects. I wanted to implement the CRUD operations for the both the model object. For Muscle object it was very straight forward but for the Exercise Object for the put/Update operation I am getting the following error "JSON parse error: Unresolved forward references for: ; nested exception is com.fasterxml.jackson.databind.deser.UnresolvedForwardReference" . And further more if I try to delete one exercise, somehow all the data of muscle and exercise gets deleted.
This is my muscle class
package com.fazla.exercise.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
#Entity
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id")
public class Muscle {
#Id
// #Column(unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column
private String name;
#OneToMany(mappedBy="muscle", cascade= CascadeType.ALL, fetch = FetchType.EAGER)
// #JoinColumn(name="muscle_id")
// #Column(nullable = true)
private List<Exercise> exercises = new ArrayList<>();
public Muscle() {
}
public Muscle(String name, List<Exercise> exercises) {
super();
this.name = name;
this.exercises = exercises;
}
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 List<Exercise> getExercises() {
return exercises;
}
public void setExercises(List<Exercise> exercises) {
this.exercises = exercises;
}
// #Override
// public String toString() {
// return "Muscle [id=" + id + ", name=" + name + ", exercises=" + exercises + "]";
// }
}
This is my Exercise Object
package com.fazla.exercise.model;
import javax.persistence.CascadeType;
import javax.persistence.Column;
//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.JoinTable;
import javax.persistence.ManyToOne;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
#Entity
//#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="id")
public class Exercise {
#Id
#Column(unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column
private String name;
#Column
private String description;
//As there will be many exercise under one muscle that is why manytoone
//object references an unsaved transient instance - save the transient instance before flushing
//that is why need to add the cascading dependencies
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="muscle_id")
// #JsonIgnore
// #JoinTable(name="muscle")
private Muscle muscle;
public Exercise() {
}
public Exercise(String name, String description, Muscle muscle) {
super();
this.name = name;
this.description = description;
this.muscle = muscle;
}
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 String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Muscle getMuscle() {
return muscle;
}
public void setMuscle(Muscle muscle) {
this.muscle = muscle;
}
// #Override
// public String toString() {
// return "Exercise [id=" + id + ", name=" + name + ", description=" + description + ", muscle=" + muscle + "]";
// }
}
This is the MuscleController
package com.fazla.exercise.controller;
import java.util.List;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.fazla.exercise.model.Muscle;
import com.fazla.exercise.repository.MuscleRepository;
#RestController
public class MuscleController {
private MuscleRepository muscleRepository;
public MuscleController(MuscleRepository muscleRepository) {
this.muscleRepository = muscleRepository;
}
#GetMapping("/muscle")
List<Muscle> all(){
return muscleRepository.findAll();
}
#PostMapping("/muscle")
Muscle newMuscle(#RequestBody Muscle muscle) {
return muscleRepository.save(muscle);
}
#GetMapping("/muscle/{id}")
Muscle one(#PathVariable Long id) {
return muscleRepository.findById(id)
.orElse(null);
}
#PutMapping("/muscle/{id}")
Muscle updateMuscle(#RequestBody Muscle newMuscle, #PathVariable Long id) {
return muscleRepository.findById(id)
.map(muscle ->{
muscle.setName(newMuscle.getName());
muscle.setExercises(newMuscle.getExercises());
return muscleRepository.save(muscle);
})
.orElse(null);
}
#DeleteMapping("/muscle/{id}")
void deleteMuscle(#PathVariable Long id){
muscleRepository.deleteById(id);
}
}
This is the ExerciseController Class
package com.fazla.exercise.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.fazla.exercise.model.Exercise;
import com.fazla.exercise.model.Muscle;
import com.fazla.exercise.repository.ExerciseRepository;
import com.fazla.exercise.repository.MuscleRepository;
#RestController
public class ExerciseController {
private ExerciseRepository repository;
private MuscleRepository muscleRepository;
#Autowired
public ExerciseController(ExerciseRepository repository, MuscleRepository muscleRepository) {
super();
this.repository = repository;
this.muscleRepository=muscleRepository;
}
#GetMapping("/exercise")
public List<Exercise> getAll() {
return repository.findAll();
}
#PostMapping("/exercise")
public Exercise newExercise(#RequestBody Exercise newExercise, #RequestParam
Long muscleId) {
Muscle muscle = muscleRepository.findById(muscleId).orElse(null);
newExercise.setMuscle(muscle);
return repository.save(newExercise);
}
#DeleteMapping("/exercise/{id}")
public void deleteExercise(#PathVariable Long id) {
repository.deleteById(id);
}
#GetMapping("/exercise/{id}")
public Exercise one(#PathVariable Long id) {
return repository.findById(id).orElse(null);
}
#PutMapping("/exercise/{id}")
public Exercise updateExercise(#RequestBody Exercise newExercise, #PathVariable Long id) {
return repository.findById(id)
.map(//map a function which maps
e ->{
e.setName(newExercise.getName());
e.setDescription(newExercise.getDescription());
e.setMuscle(newExercise.getMuscle());
return repository.save(e);
})
.orElse(null);
}
}
This is my ExerciseRepository
package com.fazla.exercise.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.fazla.exercise.model.Exercise;
public interface ExerciseRepository extends JpaRepository<Exercise, Long> {
}
This is the MuscleRepository
package com.fazla.exercise.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.fazla.exercise.model.Muscle;
public interface MuscleRepository extends JpaRepository<Muscle, Long>{
}
This is the error if I try the put request or update the exercise object
"timestamp": "2018-10-10T06:30:46.924+0000",
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Unresolved forward references for: ; nested exception is com.fasterxml.jackson.databind.deser.UnresolvedForwardReference: Unresolved forward references for: \n at [Source: (PushbackInputStream); line: 23, column: 1]Object id [1] (for `com.fazla.exercise.model.Muscle`) at [Source: (PushbackInputStream); line: 13, column: 28], Object id [1] (for `com.fazla.exercise.model.Muscle`) at [Source: (PushbackInputStream); line: 19, column: 28].",
"path": "/api/exercise/14"
The solution was, adding orphanRemoval= true on the Parent/ Muscle model
#OneToMany(mappedBy="muscle", cascade= CascadeType.ALL, orphanRemoval= true)
private List<Exercise> exercises = new ArrayList<>();
Removing the cascade= CascadeType.ALL in the child/ Exercise model
#ManyToOne
private Muscle muscle;
And for the updateExercise changing the Request by finding the muscle which the exercise belongs to and muscleRepository.findById(muscleId) and setting it in the new exercise object.
#PutMapping("/exercise/{id}")
public Exercise updateExercise(#RequestBody Exercise newExercise, #PathVariable Long id, #RequestParam Long muscleId) {
Muscle muscle = muscleRepository.findById(muscleId).orElse(null);
return repository.findById(id)
.map(//map a function which maps
e ->{
e.setName(newExercise.getName());
e.setDescription(newExercise.getDescription());
e.setMuscle(muscle);
return repository.save(e);
})
.orElse(null);
}
on your Exercise you have
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="muscle_id")
private Muscle muscle;
and on your Musce you have
#OneToMany(cascade= CascadeType.ALL)
private List<Exercise> exercises = new ArrayList<>();
Cascade.ALL propagates all actions on your Object and if you delete a Excercise, DELETE is propagated to all referenced objects
Bacause you just want to propagate UPDATES replace
cascade = CascadeType.ALL
with
cascade = CascadeType.SAVE_UPDATE
I want to establish one to many relation between table vendor detail and product detail. like one vendor can have multiple products. but when i am inserting data into table its inserting all the four fields but not mapping vendorid into ProductDetail Table
and query generated is this.
Hibernate: insert into ProductInfo (productCategory, productDetails, productPrice, VendorId) values (?, ?, ?, ?) It shuld map vendor ID also but in table its empty.
VendorDetail.java
package com.cts.entity;
import javax.persistence.*;
#Entity
#Table(name = "VendorInfo")
public class VendorDetails {
#Id
#Column
private Long VendorId;
#OneToMany
private ProductDetails productdetail;
#Column
private String VendorName;
#Column
private String Password;
public String getVendorName() {
return VendorName;
}
public void setVendorName(String vendorName) {
VendorName = vendorName;
}
public Long getVendorId() {
return VendorId;
}
public void setVendorId(Long vendorId) {
VendorId = vendorId;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
Password = password;
}
}
ProductDetails.java
package com.cts.entity;
import javax.persistence.CascadeType;
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.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity#Table(name = "ProductInfo")
public class ProductDetails {
#ManyToOne(cascade = CascadeType.ALL)#JoinColumn(name = "VendorId")
private VendorDetails vendordetails;
public ProductDetails() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private int productId;
#Column
private String productCategory;
#Column
private String productDetails;
#Column
private String productPrice;
public VendorDetails getVendordetails() {
return vendordetails;
}
public void setVendordetails(VendorDetails vendordetails) {
this.vendordetails = vendordetails;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public String getProductCategory() {
return productCategory;
}
public void setProductCategory(String productCategory) {
this.productCategory = productCategory;
}
public String getProductDetails() {
return productDetails;
}
public void setProductDetails(String productDetails) {
this.productDetails = productDetails;
}
public String getProductPrice() {
return productPrice;
}
public void setProductPrice(String productPrice) {
this.productPrice = productPrice;
}
}
DAO class ProductDetailDaoImpl.java
package com.cts.Dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.cts.entity.ProductDetails;
import com.cts.entity.to.ProductDetailsTo;
#Repository
public class ProductDetailDaoImpl implements ProductDetailDao {
#Autowired
SessionFactory sessionFactory;
#Transactional
public boolean saveProductInfo(ProductDetailsTo productTo) {
System.out.println("M in Registration DAO");
System.out.println(productTo.getProductCategory());
System.out.println(productTo.getProductDetails());
System.out.println(productTo.getProductId());
System.out.println(productTo.getProductPrice());
//getting productTo data to entity class
ProductDetails prodet = productTo.getEntity();
System.out.println("Value of product details is:" + prodet.getProductDetails());
sessionFactory.getCurrentSession().save(prodet);
return false;
}
}
VendorDetails has many ProductDetails so you need to make one to many annotation like this:-
#OneToMany(mappedBy="vendordetails") //mappedBy value will be what you declared //in ProductDetails class.
private Collection<ProductDetails> productdetail=new ArrayList<ProductDetails>;
and create the setter and getter of this.
Now in ProductDetails class you need to annotate many to one like this:-
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "VendorId")
private VendorDetails vendordetails;
Then a new column named 'VendorId' will be create in table 'ProductInfo' and since declare mappedBy value="vendordetails" so each vendor id would be insert.
I think you should replace the code
#OneToMany
private ProductDetails productdetail;
to
#OneToMany
private Set productdetailSet;
And create setter and getter for this.
You can visit the blog http://gaurav1216.blogspot.in/2014/01/hibernate-tutorial-day-5.html for one to many using annotation.