I have an Account class for a job search application I am building which contains a Linked List of Education instances (just university name, gpa, etc). I would like to have an HTTP Post request to add an element to that list:
@PostMapping("/education/{id}")
void newAccount(@RequestBody Education newEducation, @PathVariable Long id) {
Account a = repository.findById(id).orElseThrow(() -> new AccountNotFoundException(id));
a.addEducation(newEducation);
}
This is the account class:
import java.util.LinkedList;
import java.util.Objects;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Account {
private @Id @GeneratedValue Long id;
private String name;
private String email;
private String phone;
private LinkedList<Education> education;
Account() {}
Account(String name, String email, String phone) {
education = new LinkedList<>();
this.setName(name);
this.setEmail(email);
this.setPhone(phone);
}
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public LinkedList<Education> getEducation() {
return education;
}
public void addEducation(Education e) {
education.add(e);
}
@Override
public boolean equals(Object o) {
if (this==o)
return true;
if (!(o instanceof Account))
return false;
Account acc = (Account)o;
return name.equals(acc.name);
}
@Override
public int hashCode() {
return Objects.hash(this.id, this.name);
}
@Override
public String toString() {
String edu="";
if (!this.education.isEmpty())
{
edu+=", \"Education: [";
for (Education e: this.education)
{
edu+=e.toString();
}
edu+="]";
}
String s = "Account{";
s += String.format("\"id\": \"%s\", ", this.id);
s += String.format("\"name\": \"%s\", ", this.name);
s += String.format("\"email\": \"%s\", ", this.email);
s += String.format("\"phone\": \"%s\"", this.phone);
s += edu;
s += "}";
return s;
}
}
However, when I actually send a post request with education data (for an already existing user), it does not post it. It does print the Account a properly (with the added education) but does not actually update the database.
Additionally, this is another class I have:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class LoadDatabase {
private static final Logger log =
LoggerFactory.getLogger(LoadDatabase.class);
@Bean
CommandLineRunner initDatabase(AccountRepository repository) {
return args -> {
log.info("Preloading " + repository.save(new Account("Alex", "[email protected]", "214")));
Account a= new Account("Bob", "[email protected]", "972");
//a.addEducation(new Education("B.S.", "Uni", 3.64));
//log.info("Preloading " + repository.save(a));
};
}
}
Uncommenting a.addEducation and log.info causes a runtime error (keeping either one of them would not trigger that):
java.lang.IllegalStateException: Failed to execute CommandLineRunner at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:779) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] at com.project933.Project933Application.main(Project933Application.java:10) ~[classes/:na] Caused by: org.springframework.orm.jpa.JpaSystemException: could not serialize; nested exception is org.hibernate.type.SerializationException: could not serialize at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:353) ~[spring-orm-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255) ~[spring-orm-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528) ~[spring-orm-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:154) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] at com.sun.proxy.$Proxy90.save(Unknown Source) ~[na: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:566) ~[na:na] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:205) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] at com.sun.proxy.$Proxy64.save(Unknown Source) ~[na:na] at com.project933.LoadDatabase.lambda$0(LoadDatabase.java:19) ~[classes/:na] at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795) ~[spring-boot-2.3.4.RELEASE.jar:2.3.4.RELEASE] ... 5 common frames omitted Caused by: org.hibernate.type.SerializationException: could not serialize at org.hibernate.internal.util.SerializationHelper.serialize(SerializationHelper.java:119) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.internal.util.SerializationHelper.serialize(SerializationHelper.java:144) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.internal.util.SerializationHelper.clone(SerializationHelper.java:75) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.type.descriptor.java.SerializableTypeDescriptor$SerializableMutabilityPlan.deepCopyNotNull(SerializableTypeDescriptor.java:41) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.type.descriptor.java.SerializableTypeDescriptor$SerializableMutabilityPlan.deepCopyNotNull(SerializableTypeDescriptor.java:32) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.type.descriptor.java.MutableMutabilityPlan.deepCopy(MutableMutabilityPlan.java:35) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.type.AbstractStandardBasicType.deepCopy(AbstractStandardBasicType.java:308) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.type.AbstractStandardBasicType.deepCopy(AbstractStandardBasicType.java:304) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.type.TypeHelper.deepCopy(TypeHelper.java:55) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:279) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:135) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:185) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:128) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:55) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:721) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:707) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] 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:566) ~[na:na] at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:314) ~[spring-orm-5.2.9.RELEASE.jar:5.2.9.RELEASE] at com.sun.proxy.$Proxy87.persist(Unknown Source) ~[na:na] at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:554) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE] 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:566) ~[na:na] at org.springframework.data.repository.core.support.ImplementationInvocationMetadata.invoke(ImplementationInvocationMetadata.java:72) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:382) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:205) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:549) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:155) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE] ... 21 common frames omitted Caused by: java.io.NotSerializableException: com.project933.Education at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185) ~[na:na] at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349) ~[na:na] at java.base/java.util.LinkedList.writeObject(LinkedList.java:1135) ~[na: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:566) ~[na:na] at java.base/java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1145) ~[na:na] at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1497) ~[na:na] at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433) ~[na:na] at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179) ~[na:na] at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349) ~[na:na] at org.hibernate.internal.util.SerializationHelper.serialize(SerializationHelper.java:115) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final] ... 63 common frames omitted
Could anyone please explain why I am having problems with inserting the Education instances into the Account database? I am using JpaRepository.
Thanks!
edit: This is the Education class:
public class Education {
private String degree;
private String institute;
private double gpa;
Education(String degree, String institute, double gpa) {
this.setDegree(degree);
this.setInstitute(institute);
this.setGpa(gpa);
}
public String getDegree() {
return degree;
}
public void setDegree(String degree) {
this.degree = degree;
}
public String getInstitute() {
return institute;
}
public void setInstitute(String institute) {
this.institute = institute;
}
public double getGpa() {
return gpa;
}
public void setGpa(double gpa) {
this.gpa = gpa;
}
@Override
public String toString() {
String s = "{";
s += s += String.format("\"degree\": \"%s\"", this.degree);
s += String.format("\"institute\": \"%s\"", this.institute);
s += String.format("\"gpa\": %.2f", this.gpa);
s += "}";
return s;
}
}