I am making a basic application to send an insert to a database, as a test I have been executing a simple findAll () to test the repository, but it always gives me NullPointer
I am aware that it is something very basic and also that I am missing something.
Thank you.
This is the main
#SpringBootApplication
public class ExampleApplication {
#Autowired
private static DataRepository dataRepository;
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
System.out.println(dataRepository.findAll());
}
}
Model
#Entity
public class Data {
#Id
private Long id;
private String content;
public Data(Long id, String content) {
super();
this.id = id;
this.content = content;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
#Override
public String toString() {
return "Data [id=" + id + ", content=" + content + "]";
}
}
Repository
#Repository
public interface DataRepository extends JpaRepository<Data, Long> {
}
Controller
#RestController
public class DataController {
#Autowired
private DataRepository dataRepository;
#GetMapping("/show")
public List<Data> findCities(Data data) {
return dataRepository.findAll();
}
}
Error
2020-04-07 10:27:14.323 INFO 19892 --- [ main] com.example.demo.ExampleApplication : Starting ExampleApplication on DESKTOP-ARNRCSA with PID 19892 (C:\Users\David\Documents\workspace-spring-tool-suite-4-4.5.1.RELEASE\example\target\classes started by David in C:\Users\David\Documents\workspace-spring-tool-suite-4-4.5.1.RELEASE\example)
2020-04-07 10:27:14.326 INFO 19892 --- [ main] com.example.demo.ExampleApplication : No active profile set, falling back to default profiles: default
2020-04-07 10:27:14.739 INFO 19892 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2020-04-07 10:27:14.794 INFO 19892 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 48ms. Found 1 JPA repository interfaces.
2020-04-07 10:27:15.147 INFO 19892 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2020-04-07 10:27:15.261 INFO 19892 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2020-04-07 10:27:15.300 INFO 19892 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-04-07 10:27:15.363 INFO 19892 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.4.12.Final
2020-04-07 10:27:15.490 INFO 19892 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-04-07 10:27:15.588 INFO 19892 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL55Dialect
2020-04-07 10:27:15.832 INFO 19892 --- [ main] org.hibernate.tuple.PojoInstantiator : HHH000182: No default (no-argument) constructor for class: com.example.demo.Data (class must be instantiated by Interceptor)
2020-04-07 10:27:16.057 INFO 19892 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-04-07 10:27:16.063 INFO 19892 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-04-07 10:27:16.066 INFO 19892 --- [ main] f.a.AutowiredAnnotationBeanPostProcessor : Autowired annotation is not supported on static fields: private static com.example.demo.DataRepository com.example.demo.ExampleApplication.dataRepository
2020-04-07 10:27:16.417 INFO 19892 --- [ main] com.example.demo.ExampleApplication : Started ExampleApplication in 2.399 seconds (JVM running for 3.041)
Exception in thread "main" java.lang.NullPointerException
at com.example.demo.ExampleApplication.main(ExampleApplication.java:17)
2020-04-07 10:27:16.422 INFO 19892 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-04-07 10:27:16.424 INFO 19892 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2020-04-07 10:27:16.428 INFO 19892 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource
try this
#SpringBootApplication
public class ExampleApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
DataRepository dataRepository = context.getBean(DataRepository.class);
System.out.println(dataRepository.findAll());
}
}
you can not use autowire with static field unless you use postConstruct
Jpa needs defaut constructor so put it into your Data class
Related
I implemented a simple Spring Boot application using the following classes:
Application Class:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#ComponentScan(basePackageClasses = CustomerController.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Model Class:
public class Customer {
private Long id;
private String Name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
Controller Class:
#RestController
public class CustomerController {
#RequestMapping(name="/customer", method=RequestMethod.GET)
public Customer getCustomer(#RequestParam Long id) {
Customer cust = new Customer();
cust.setId(id);
cust.setName("George");
return cust;
}
#RequestMapping(name="/customer", method=RequestMethod.POST, consumes = "application/json")
public Customer createCustomer(#RequestBody Customer cust) {
return cust;
}
}
The application was initiated as Spring Boot and produced the following logs:
2022-09-14 13:28:17.448 INFO 13564 --- [ main] Application : Starting Application using Java 18 on DESKTOP with PID 13564
2022-09-14 13:28:17.453 INFO 13564 --- [ main] Application : No active profile set, falling back to 1 default profile: "default"
2022-09-14 13:28:18.757 INFO 13564 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-09-14 13:28:18.773 INFO 13564 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-09-14 13:28:18.773 INFO 13564 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.65]
2022-09-14 13:28:18.904 INFO 13564 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-09-14 13:28:18.904 INFO 13564 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1348 ms
2022-09-14 13:28:19.332 INFO 13564 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-09-14 13:28:19.342 INFO 13564 --- [ main] Application : Started Application in 2.661 seconds (JVM running for 3.766)
2022-09-14 13:28:27.493 INFO 13564 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-09-14 13:28:27.494 INFO 13564 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-09-14 13:28:27.495 INFO 13564 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
When i start postman invoke the following:
GET http://localhost:8080/customer?id=1
and i get the following error:
{
"timestamp": "2022-09-14T10:28:27.548+00:00",
"status": 404,
"error": "Not Found",
"path": "/customer"
}
Your #RequestMapping annotation should use value="customer" instead of name="customer".
Better practice is to annotate the CustomerController with #RestController and #ReqeustMapping("/customer") and mark the getCustomer method with #GetMapping, and the create Customer with #PostMapping
Like example my PostMapping:
#Controller
public class MainController {
#PostMapping("/mainaho")
public String addAho (
#RequestParam String owner,
#RequestParam String text,
#RequestParam String sn,
#RequestParam String invid,
#RequestParam String author, Map<String, Object> model) throws WriterException {
AddTmcAho addTmcAho = new AddTmcAho();
addTmcAho.addTmcAho(ahoRepo, owner, text, sn, invid, author, model);
return "mainaho";
}
}
I train with springboot and a mariadb database. When I test for data recovery, I get this message in postman:
{
"timestamp": "2022-03-03T13:53:18.609+00:00",
"status": 404,
"error": "Not Found",
"path": "/user/all"
}
. I tried several tutorials in copy paste and I always have the same message. I will also put the message that is in the console. Thank you in advance for your help.
controller
package controller;
import model.Users;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import service.UsersService;
import java.util.List;
#RestController
#RequestMapping("/user")
public class UsersController {
private UsersService usersService;
public UsersController(UsersService usersService) {
this.usersService = usersService;
}
#GetMapping("/all")
public ResponseEntity<List<Users>> getUsers() {
List<Users> users = usersService.getUsers();
return new ResponseEntity<>(users, HttpStatus.OK);
}
}
Service
package service;
import model.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import repository.UsersRepository;
import java.util.List;
#Service
public class UsersService {
private UsersRepository usersRepository;
#Autowired
public UsersService(UsersRepository usersRepository) {
this.usersRepository = usersRepository;
}
public List<Users> saveUsers(List<Users>users){
return usersRepository.saveAll(users);
}
public Users saveUsers(Users users){
return usersRepository.save(users);
}
public List<Users> getUsers(){
return usersRepository.findAll();
}
public Users getUserById(int id_user){
return usersRepository.findById(id_user).orElse(null);
}
}
Respository
package repository;
import model.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface UsersRepository extends JpaRepository<Users, Integer> {
}
Model
package model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "users")
public class Users {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id_user;
#Column(name="lastname")
private String lastname;
#Column(name="email")
private String email;
#Column(name="password")
private String password;
#Column(name="phone")
private String phone;
#Column(name="adress")
private String adress;
#Column(name="city")
private String city;
#Column(name="country")
private String country;
}
Application properties
spring.jpa.hibernate.ddl-auto = update
spring.datasource.url = jdbc:mysql://localhost:3306/database
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driver-class-name= com.mysql.cj.jdbc.Driver
spring.jpa.show-sql= true
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5Dialect
Console
2022-03-03 14:52:57.479 INFO 24188 --- [ main] c.p.database.databaseApplication : No active profile set, falling back to 1 default profile: "default"
2022-03-03 14:52:58.412 INFO 24188 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2022-03-03 14:52:58.435 INFO 24188 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 8 ms. Found 0 JPA repository interfaces.
2022-03-03 14:52:59.190 INFO 24188 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-03-03 14:52:59.204 INFO 24188 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-03-03 14:52:59.204 INFO 24188 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.58]
2022-03-03 14:52:59.370 INFO 24188 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-03-03 14:52:59.370 INFO 24188 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1816 ms
2022-03-03 14:52:59.627 INFO 24188 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2022-03-03 14:52:59.696 INFO 24188 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.5.Final
2022-03-03 14:52:59.892 INFO 24188 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2022-03-03 14:53:00.046 INFO 24188 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2022-03-03 14:53:00.252 INFO 24188 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2022-03-03 14:53:00.272 INFO 24188 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
2022-03-03 14:53:00.652 INFO 24188 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2022-03-03 14:53:00.666 INFO 24188 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2022-03-03 14:53:00.722 WARN 24188 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2022-03-03 14:53:01.296 INFO 24188 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-03-03 14:53:01.317 INFO 24188 --- [ main] c.p.database.databaseApplication : Started dataBaseApplication in 4.589 seconds (JVM running for 5.786)
2022-03-03 14:53:18.493 INFO 24188 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-03-03 14:53:18.493 INFO 24188 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-03-03 14:53:18.495 INFO 24188 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
Every thing on the controller class is implemented properly and there is definitely no need for other layers implementation to share, you probably use SpringBootServletInitializer, in the main class add the #EnableWebMvc annotation and override SpringApplicationBuilder method as
#SpringBootApplication
#EnableWebMvc
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Otherwise if you use SpringApplication to sun the project make sure the main class annotated with #SpringBootApplication and be some thing like
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And final thing check the presence of spring boot starter web dependency in you pom file
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
If you do not use spring boot parent do not forget to add the proper version to web starter artifact.
I'm actually defining login with websecurity enabled, and i don't really know what is wring with my annotations that don't allow me to continue testing...
Here is the trace:
2021-10-29 13:58:09.436 INFO 10044 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-10-29 13:58:09.447 INFO 10044 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-10-29 13:58:09.447 INFO 10044 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.52]
2021-10-29 13:58:09.534 INFO 10044 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-10-29 13:58:09.534 INFO 10044 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1188 ms
2021-10-29 13:58:09.682 INFO 10044 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2021-10-29 13:58:09.731 INFO 10044 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.4.32.Final
2021-10-29 13:58:09.845 INFO 10044 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2021-10-29 13:58:09.933 INFO 10044 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-10-29 13:58:10.065 INFO 10044 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2021-10-29 13:58:10.089 INFO 10044 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL55Dialect
2021-10-29 13:58:10.628 INFO 10044 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2021-10-29 13:58:10.636 INFO 10044 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2021-10-29 13:58:10.670 WARN 10044 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-10-29 13:58:10.687 WARN 10044 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webSecurityConfig': Unsatisfied dependency expressed through field 'personaDetails'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.taxig10.demo.service.PersonaDetailsImpl' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
2021-10-29 13:58:10.687 INFO 10044 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2021-10-29 13:58:10.689 INFO 10044 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2021-10-29 13:58:10.695 INFO 10044 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
2021-10-29 13:58:10.696 INFO 10044 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2021-10-29 13:58:10.706 INFO 10044 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-10-29 13:58:10.720 ERROR 10044 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field personaDetails in com.taxig10.demo.config.WebSecurityConfig required a bean of type 'com.taxig10.demo.service.PersonaDetailsImpl' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.taxig10.demo.service.PersonaDetailsImpl' in your configuration.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
And my classes:
// app class
package com.taxig10.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class TaxiG10Application {
public static void main(String[] args) {
SpringApplication.run(TaxiG10Application.class, args);
}
}
// config class
package com.taxig10.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.taxig10.demo.service.PersonaDetailsImpl;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
private PersonaDetailsImpl personaDetails;
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(personaDetails).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/","/auth/**","public/**","/css/**","/js/**")
.permitAll().anyRequest().authenticated()
.and()
.formLogin().loginPage("/auth/index/").defaultSuccessUrl("/private/index",true).failureUrl("/auth/login?error=true")
.loginProcessingUrl("/auth/login-post").permitAll()
.and()
.logout().logoutUrl("/logout/").logoutSuccessUrl("public/index");
}
}
// IPersona class
package com.taxig10.demo.interfaces;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.taxig10.demo.modelo.Persona;
#Repository
public interface Ipersona extends CrudRepository<Persona, Integer> {
}
// IpersonaService class
package com.taxig10.demo.interfaceService;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Optional;
import javax.mail.MessagingException;
import com.taxig10.demo.modelo.Persona;
public interface IpersonaService {
public List<Persona> listar();
public Optional<Persona> listarId(int id);
public Persona save(Persona p) throws UnsupportedEncodingException, MessagingException;
public void delete(int id);
boolean login(Persona persona);
int confirm(Persona p);
boolean isAdmin(String name);
void logout(Persona persona);
// ---
public Persona getPersonaFromBD(String name);
public Persona registrar(Persona p);
}
// PersonaService class
package com.taxig10.demo.service;
#Service
public class PersonaService implements IpersonaService {
#Autowired
private Ipersona data;
#Autowired
private BCryptPasswordEncoder passwordEncoder;
#Override
public List<Persona> listar() {
return (List<Persona>)data.findAll();
}
#Override
public Persona getPersonaFromBD(String name) {
Iterator<Persona> personas = data.findAll().iterator();
while(personas.hasNext()) {
Persona cont = personas.next();
if(cont.getName().equals(name)) {
return cont;
}
}
return null;
}
}
// PersonaDetailsImpl class
package com.taxig10.demo.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.taxig10.demo.interfaceService.IpersonaService;
import com.taxig10.demo.modelo.Persona;
public class PersonaDetailsImpl implements UserDetailsService{
#Autowired
private IpersonaService personaService;
#Override
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
Persona persona = personaService.getPersonaFromBD(name);
UserBuilder builder = null;
if(persona != null) {
builder = User.withUsername(name);
builder.disabled(false);
builder.password(persona.getPwd());
builder.authorities(new SimpleGrantedAuthority("ROLE_USER"));
} else {
throw new UsernameNotFoundException("Usuario no encontrado");
}
return builder.build();
}
}
Thank you in advance <3
package com.shashank.topic;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class Topic {
#Id
private String id;
private String name;
private String description;
public Topic() {
}
public Topic(String id, String name, String description) {
super();
this.id = id;
this.name = name;
this.description = description;
}
public String getId() {
return id;
}
public void setId(String 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;
}
}
Repository is configured like this
package com.shashank.topic;
import org.springframework.data.repository.CrudRepository;
public interface TopicRepository extends CrudRepository<Topic, String> {
/***
* CURD OPERATIONS
* getAllTopics()
* getTopic(String id)
* updateTopic(Topic topic)
* deleteTopic(String id)
* */
}
This is another class
package com.shashank.topic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
#Service
public class TopicService {
#Autowired
private TopicRepository topicRepository;
public List<Topic> getAllTopics() {
List<Topic> topics = new ArrayList<>();
topicRepository.findAll().forEach(topics::add);
return topics;
}
public Optional<Topic> getTopic(String id) {
return topicRepository.findById(id);
}
public void addTopic(Topic topic) {
topicRepository.save(topic);
}
public void updateTopic(String id, Topic topic) {
topicRepository.save(topic);
}
public void deleteTopic(String id) {
topicRepository.deleteById(id);
}
}
I'm able to post the topics in my table and get as well from the postman but when I try to use put, to update the contents of the table, nothing changes.
I was trying to put the below command to update the table
{
"id": "javascript",
"name": "Update javascript",
"description": "Update javascript Description"
}
where "javascript" was already in the table, with name as "javascript" and description as "javascript description"
Here is my spring console log
2021-03-03 17:33:05.625 INFO 9848 --- [ main]
com.shashank.CourseApiDataApplication : Starting
CourseApiDataApplication using Java 13.0.2 on DESKTOP-FGT8D3V with PID 9848
(D:\MavenProjects\course-api-data\target\classes started by shash in
D:\MavenProjects\course-api-data)
2021-03-03 17:33:05.628 INFO 9848 --- [ main]
com.shashank.CourseApiDataApplication : No active profile set, falling
back to default profiles: default
2021-03-03 17:33:06.262 INFO 9848 --- [ main]
.s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA
repositories in DEFAULT mode.
2021-03-03 17:33:06.290 INFO 9848 --- [ main]
.s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository
scanning in 23 ms. Found 1 JPA repository interfaces.
2021-03-03 17:33:06.618 INFO 9848 --- [ main]
o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s):
8080 (http)
2021-03-03 17:33:06.623 INFO 9848 --- [ main]
o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-03-03 17:33:06.624 INFO 9848 --- [ main]
org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache
Tomcat/9.0.43]
2021-03-03 17:33:06.720 INFO 9848 --- [ main] o.a.c.c.C.[Tomcat].
[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-03-03 17:33:06.720 INFO 9848 --- [ main]
w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext:
initialization completed in 1039 ms
2021-03-03 17:33:06.876 INFO 9848 --- [ main]
o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing
PersistenceUnitInfo [name: default]
2021-03-03 17:33:06.901 INFO 9848 --- [ main]
org.hibernate.Version : HHH000412: Hibernate ORM core
version 5.4.28.Final
2021-03-03 17:33:06.964 INFO 9848 --- [ main]
o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons
Annotations {5.1.2.Final}
2021-03-03 17:33:07.016 INFO 9848 --- [ main]
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-03-03 17:33:07.018 WARN 9848 --- [ main]
com.zaxxer.hikari.util.DriverDataSource : Registered driver with
driverClassName=org.apache.derby.jdbc.EmbeddedDriver was not found, trying
direct instantiation.
2021-03-03 17:33:07.269 INFO 9848 --- [ main]
com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Driver does not
support get/set network timeout for connections. (Feature not implemented: No
details.)
2021-03-03 17:33:07.271 INFO 9848 --- [ main]
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2021-03-03 17:33:07.281 INFO 9848 --- [ main]
org.hibernate.dialect.Dialect : HHH000400: Using dialect:
org.hibernate.dialect.DerbyTenSevenDialect
2021-03-03 17:33:07.911 INFO 9848 --- [ main]
o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform
implementation:
[org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2021-03-03 17:33:07.916 INFO 9848 --- [ main]
j.LocalContainerEntityManagerFactoryBean : Initialized JPA
EntityManagerFactory for persistence unit 'default'
2021-03-03 17:33:08.134 WARN 9848 --- [ main]
JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled
by default. Therefore, database queries may be performed during view
rendering. Explicitly configure spring.jpa.open-in-view to disable this
warning
2021-03-03 17:33:08.220 INFO 9848 --- [ main]
o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService
'applicationTaskExecutor'
2021-03-03 17:33:08.460 INFO 9848 --- [ main]
o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080
(http) with context path ''
2021-03-03 17:33:08.469 INFO 9848 --- [ main]
com.shashank.CourseApiDataApplication : Started CourseApiDataApplication
in 3.207 seconds (JVM running for 3.973)
There is something unusual with your Id. Why did you consider Id as String?
It should be Long or int, So maybe your id is your main problem.
Also, It would be better that put the controller to help us to debug better. Anyway, there are some ideas.
public void updateTopic(String id, Topic topic) {
Topic myTopic = topicRepository.findById(id);
topicRepository.save(myTopic);
}
Controller
#PutMapping("/topics")
private Topic update(#RequestBody Topic topic){
topicService.updateTopic(topic);
return topic;
}
Strongly recommend you to change your ID from string to int or Long and try the above solution.
I have a unidirectional one to many relationship. The one side is PARENT, the many side is CHILD. For one PARENT there can be many CHILD. But for a CHILD there is exactly one PARENT. On the Java side the relation is unidirectional, I need to access the CHILDS of a PARENT, but I don't want to store the PARENT for CHILDS. So these are the objects:
Parent:
#Entity
public class Parent {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String job;
#OneToMany(targetEntity = Child.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "PARENT_ID")
private Set<Child> childs;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getJob() { return job; }
public void setJob(String job) { this.job = job; }
public Set<Child> getChilds() {
if(childs != null) { return childs; }
else {
childs = new HashSet<Child>();
return childs;
}
}
public void setChilds(Set<Child> childs) { this.childs = childs; }
}
Child:
#Entity
public class Child {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String hobby;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getHobby() { return hobby; }
public void setHobby(String hobby) { this.hobby = hobby; }
}
This is the code which creates a child, a parent with that child and then saves parent:
#Test
public void test() {
Child c = new Child();
c.setHobby("hobby");
Parent p = new Parent();
p.setJob("test");
p.getChilds().add(c);
parentRepository.save(p);
}
Then when I run the code there is an error because Hibernate does not set the PARENT_ID on CHILD when inserting it. In the log it is clear that Hibernate retrieved the two ids needed from the sequence generator YET it leaves CHILD.PARENT_ID null:
2020-07-28 13:21:00.689 INFO 16295 --- [ main] jpa_hibernate_spring_boot.MyTest : Starting MyTest on riskop-ESPRIMO-P556 with PID 16295 (started by riskop in /home/riskop/Documents/privat/java/jpa_hibernate_spring_boot)
2020-07-28 13:21:00.690 INFO 16295 --- [ main] jpa_hibernate_spring_boot.MyTest : No active profile set, falling back to default profiles: default
2020-07-28 13:21:00.950 INFO 16295 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFERRED mode.
2020-07-28 13:21:00.988 INFO 16295 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 32ms. Found 1 JPA repository interfaces.
2020-07-28 13:21:01.362 INFO 16295 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2020-07-28 13:21:01.491 INFO 16295 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2020-07-28 13:21:01.608 INFO 16295 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-07-28 13:21:01.660 INFO 16295 --- [ task-1] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-07-28 13:21:01.703 INFO 16295 --- [ task-1] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.4.18.Final
2020-07-28 13:21:01.743 INFO 16295 --- [ main] DeferredRepositoryInitializationListener : Triggering deferred initialization of Spring Data repositories…
2020-07-28 13:21:01.820 INFO 16295 --- [ task-1] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-07-28 13:21:01.977 INFO 16295 --- [ task-1] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2020-07-28 13:21:02.388 INFO 16295 --- [ task-1] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-07-28 13:21:02.393 INFO 16295 --- [ task-1] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-07-28 13:21:02.521 INFO 16295 --- [ main] DeferredRepositoryInitializationListener : Spring Data repositories initialized!
2020-07-28 13:21:02.526 INFO 16295 --- [ main] jpa_hibernate_spring_boot.MyTest : Started MyTest in 1.983 seconds (JVM running for 2.575)
2020-07-28 13:21:02.578 DEBUG 16295 --- [ main] org.hibernate.SQL :
call next value for hibernate_sequence
2020-07-28 13:21:02.595 DEBUG 16295 --- [ main] org.hibernate.SQL :
call next value for hibernate_sequence
2020-07-28 13:21:02.601 DEBUG 16295 --- [ main] org.hibernate.SQL :
insert
into
parent
(job, id)
values
(?, ?)
2020-07-28 13:21:02.603 TRACE 16295 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [test]
2020-07-28 13:21:02.604 TRACE 16295 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [1]
2020-07-28 13:21:02.605 DEBUG 16295 --- [ main] org.hibernate.SQL :
insert
into
child
(hobby, id)
values
(?, ?)
2020-07-28 13:21:02.606 TRACE 16295 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [hobby]
2020-07-28 13:21:02.606 TRACE 16295 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [2]
2020-07-28 13:21:02.607 WARN 16295 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23502, SQLState: 23502
2020-07-28 13:21:02.607 ERROR 16295 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : NULL not allowed for column "PARENT_ID"; SQL statement:
insert into child (hobby, id) values (?, ?) [23502-200]
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.105 s <<< FAILURE! - in jpa_hibernate_spring_boot.MyTest
[ERROR] test Time elapsed: 0.089 s <<< ERROR!
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
at jpa_hibernate_spring_boot.MyTest.test(MyTest.java:33)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
at jpa_hibernate_spring_boot.MyTest.test(MyTest.java:33)
Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException:
NULL not allowed for column "PARENT_ID"; SQL statement:
insert into child (hobby, id) values (?, ?) [23502-200]
at jpa_hibernate_spring_boot.MyTest.test(MyTest.java:33)
How should I fix it?
Note that if I remove the not null constraint from CHILD.PARENT_ID, then the code works. But I obviously need that check.
The whole code is here:
https://github.com/riskop/jpa_hibernate_problem_parent_id_is_not_filled_by_hibernate
Thank you jwpol for the "nullable = false" info! If I apply that to Parent:
#JoinColumn(name = "PARENT_ID", nullable = false)
private Set<Child> childs;
Then it starts working!
Yet I am curious why Hibernate does not do this by default and why does it try to update PARENT_ID even if "nullable = false" is given:
2020-07-28 14:16:02.161 INFO 20458 --- [ main] jpa_hibernate_spring_boot.MyTest : Started MyTest in 2.007 seconds (JVM running for 2.599)
2020-07-28 14:16:02.220 DEBUG 20458 --- [ main] org.hibernate.SQL :
call next value for hibernate_sequence
2020-07-28 14:16:02.242 DEBUG 20458 --- [ main] org.hibernate.SQL :
call next value for hibernate_sequence
2020-07-28 14:16:02.250 DEBUG 20458 --- [ main] org.hibernate.SQL :
insert
into
parent
(job, id)
values
(?, ?)
2020-07-28 14:16:02.252 TRACE 20458 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [test]
2020-07-28 14:16:02.253 TRACE 20458 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [1]
2020-07-28 14:16:02.255 DEBUG 20458 --- [ main] org.hibernate.SQL :
insert
into
child
(hobby, parent_id, id)
values
(?, ?, ?)
2020-07-28 14:16:02.255 TRACE 20458 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [hobby]
2020-07-28 14:16:02.255 TRACE 20458 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [1]
2020-07-28 14:16:02.256 TRACE 20458 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [2]
2020-07-28 14:16:02.260 DEBUG 20458 --- [ main] org.hibernate.SQL :
update
child
set
parent_id=?
where
id=?
2020-07-28 14:16:02.261 TRACE 20458 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [1]
2020-07-28 14:16:02.261 TRACE 20458 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [2]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.144 s - in jpa_hibernate_spring_boot.MyTest
Do you have any idea why this seemingly unneccessary update happens?
Vlad Mihalcea has a good article on exactly what your are doing. It can be found at https://vladmihalcea.com/the-best-way-to-map-a-onetomany-association-with-jpa-and-hibernate.
Basically when you provide the #JoinColumn annotation Hibernate will perform a persist on the parent first, will persist the children minus foreign key second, and then update the child foreign keys with the parent's primary key. This follows Hibernate's flush order. To prevent the additional update his suggestion is to make the association bi-directional and manage the association bidirectionally via helper methods on the parent.
Use
#JoinColumn(name = "PARENT_ID", nullable = false), you will tell hibernate that there is not null constraint.