I have spent the whole weekend trying to debug this piece of code. I have a Spring RestController :
import com.tsakirogf.schedu.model.ContactMean;
import com.tsakirogf.schedu.model.DefaultContactMean;
import com.tsakirogf.schedu.model.human.Business;
import com.tsakirogf.schedu.services.BusinessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.util.Optional;
import java.util.Set;
@RestController
@RequestMapping("api/v1/business/")
public class BusinessController
{
@Autowired
BusinessService businessService;
@GetMapping(value = "businesss")
Iterable<Business> list()
{
Iterable<Business> retVal = businessService.findAll();
return retVal;
}
@RequestMapping(value = "business", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
Business create(@RequestBody Business business)
{
CollectionOfContactMethods collectionOfContact = business.getContact();
collectionOfContact.setBusiness(business);
Set<ContactMean> contactMeanSet = collectionOfContact.getContactMeans();
DefaultContactMean defaultContactMeanSet = collectionOfContact.getDefaultContactMean();
defaultContactMeanSet.getCollectionOfContactMethodsDefault().setId(collectionOfContact.getId());
for (ContactMean element : contactMeanSet)
{
element.setCollectionOfContactMethods(collectionOfContact);
}
collectionOfContact.setDefaultContactMean(defaultContactMeanSet);
business.setContact(collectionOfContact);
Business retval = businessService.save(business);
return retval;
}
@RequestMapping(value = "business/{id}", method = RequestMethod.GET )
Optional<Business> get(@PathVariable Long id)
{
return businessService.findById(id);
}
}
And the service :
public interface BusinessService extends CrudRepository<Business, Long>
{
}
This is the model :
@Table(name = "business")
public class Business
{
@Id
@Column(name = "business_id", nullable = false)
private Long id;
@JsonProperty("name")
private String name;
@Embedded
@JsonProperty("address")
private Address address;
@OneToMany(mappedBy = "business",
cascade = CascadeType.ALL,
fetch = FetchType.LAZY)
@JsonProperty("operatives")
@JsonIgnore
Set<Professional> operatives;
@OneToOne(mappedBy = "business",
cascade = CascadeType.ALL,
fetch = FetchType.LAZY,
optional = false)
@JsonBackReference
@JsonProperty("contact_numbers")
private CollectionOfContactMethods contact;
public Business()
{
}
// Getters and Setters
}
When I send a POST request like this :
Where I got the following
{ "timestamp": "2021-11-01T08:59:06.343 00:00", "status": 500, "error": "Internal Server Error", "path": "/api/v1/business/business" }
I debug and I am getting InvocationTargetException as seen below
This is the controller, right before save() which seems to throw :

I found this article posted in a similar event in StackOverflow but I don't think that's what is happening in this case since I have only H2 database for now. This is application.properties file :
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.jpa.hibernate.hbm2ddl.auto=create
I would appreciate any ideas. Thanks for your time.
CodePudding user response:
If you look at your last screenshot you see a message indicating that there is an id field that has no value.
In your entity you have the following declaration of your id field:
@Id
@Column(name = "business_id", nullable = false)
private Long id;
Which indicates to hibernate that it shouldn't generate a key or that there is no database assigned one. Which means you will manually need to set the value for id. If you don't you will run into this exception.
Now I assume that this was a mistake and that you actually wanted to have a sequence or auto-incremented id field. For this add the @GeneratedValue annotation to add this behavior.
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE))
@Column(name = "business_id", nullable = false)
private Long id;
This will instruct hibernate to use a sequence to generate the id upon inserting the entity. If your database supports identity columns you might want to use GenerationType.IDENTITY instead of GenerationType.SEQUENCE.


