Spring boot JPA null pointer exception - java

I am developing an JavaFx application with spring boot,JPA, and H2. I have a user entity when I try to add a new user into the DB it throws NPE in the controller on the button's click action. As it is seen I use only autowire notation. I researched
but findings did not help out. Any help please?
package com.core;
#SpringBootApplication
#Import(SharedSpringConfiguration.class)
public class Runner extends Application {
private ConfigurableApplicationContext context;
public static void main(String[] args) {
launch(args);
}
#Override
public void init() {
context = SpringApplication.run(Runner.class);
}
}
package com.dao;
#Entity
#Table(name = "user")
public class User {
#Id
#Column(name = "id", updatable = false, nullable = false)
private long ID;
#Column(nullable = false)
private String userName;
#Column(nullable = false)
private String userPass;
public User() {
}
public User(long ID, String userName, String userPass) {
this.ID = ID;
this.userName = userName;
this.userPass = userPass;
}
}
package com.service;
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
public UserService() {
}
public void saveUser(User user) {
userRepository.save(user);
}
}
package com.repository;
public interface UserRepository extends CrudRepository<User, Long> {}
package com.controller
#Controller
public class MethodController implements Initializable {
#Autowired
private UserService userService;
#FXML
void methodSave(MouseEvent event) {
userService.saveUser(new User(11, "TestUser", "noPass")); //Throws NPE. Indicates that userService is null. But I autowire the userService.
}
}

I don't know what's in SharedSpringConfiguration, but you probably need #EnableJpaRepositories on one of your configuration classes. #Repository on the CrudRepo should be unnecessary.

Change your SpringBootApplication package from com.core to com
because SpringBootApplication by default will scan only that packages and sub packages.
else
add #ComponentScan annotation in SpringBootApplication and scan the packages.

Related

Spring Boot - "this.peopleService" is null?

I'm a bit new to Spring Boot and I'm trying to create model/repo/service/serviceImp/controller type of architecture.
After I try to make a this get request:
http://localhost:8080/api/v1/people/name?name=steve
and I get this error (I created a couple of people in DB):
"java.lang.NullPointerException: Cannot invoke \"com.project.Springbootbackend.service.PeopleService.findAllByName(String)\" because \"this.peopleService\" is null\r\n\tat com.project.Springbootbackend.controller.PeopleController.findAllByName(PeopleController.java:24)
This is my code:
People(entity)
#Entity
public class People {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "name")
private String name;
#Column(name = "surname")
private String surname;
#Column(name = "email")
private String email;
...
//constructor + get/set
PeopleController
#RestController
#RequestMapping("/api/v1/people")
#RequiredArgsConstructor
public class PeopleController {
private PeopleService peopleService;
#GetMapping("/name")
public ResponseEntity<List<People>> findAllByName(#RequestParam String name) {
return ResponseEntity.ok().body(peopleService.findAllByName(name));
}
}
PeopleRepo
public interface PeopleRepository extends JpaRepository<People, Integer> {
List<People> findAllByName(String name);
}
PeopleService
public interface PeopleService {
List<People> findAllByName(String name);
}
PeopleServiceImp
#RequiredArgsConstructor
#Service
public class PeopleServiceImp implements PeopleService {
PeopleRepository peopleRepository;
#Override
public List findAllByName(String name) {
return (List) ResponseEntity.ok(peopleRepository.findAllByName(name));
}
}
Thx guys in advance.
*SOLUTION:
Entity, service & repository is the same.
ServiceImp and controller changes are down belowe:
Controller:
#RestController
#RequestMapping("/api/v1/people")
public class PeopleController {
private PeopleService peopleService;
public PeopleController(PeopleService peopleService) {
this.peopleService = peopleService;
}
#GetMapping("/name")
public ResponseEntity<List<People>> findAllByName(#RequestParam String name) {
return ResponseEntity.ok().body(peopleService.findAllByName(name));
}
}
ServiceImp
#Service
public class PeopleServiceImp implements PeopleService {
private PeopleRepository peopleRepository;
public PeopleServiceImp(PeopleRepository peopleRepository) {
this.peopleRepository = peopleRepository;
}
#Override
public List<People> findAllByName(String name) {
List<People> people = peopleRepository.findAllByName(name);
return people;
}
}
Your constructor does not inject the service, because of the RequiredArgsConstructor (see Link) needs special treatment. Therefore, use final:
#RestController
#RequestMapping("/api/v1/people")
#RequiredArgsConstructor
public class PeopleController {
private final PeopleService peopleService;
#GetMapping("/name")
public ResponseEntity<List<People>> findAllByName(#RequestParam String name) {
return ResponseEntity.ok().body(peopleService.findAllByName(name));
}
}
Same here:
#RequiredArgsConstructor
#Service
public class PeopleServiceImp implements PeopleService {
private final PeopleRepository peopleRepository;
#Override
public List findAllByName(String name) {
return (List) ResponseEntity.ok(peopleRepository.findAllByName(name));
}
}
Additional hint, use a typed list:
#Override
public List<People> findAllByName(String name) {
return ResponseEntity.ok(peopleRepository.findAllByName(name));
}
Try like this:
#Autowired
private PeopleService peopleService;
#Autowired
private PeopleRepository peopleRepository;
You also need to add the #SpringBootApplication annotation in the main class of the application.
Something like that:
#SpringBootApplication
class PeopleApplication {
public static void main(String[] args) {
...
Take a look at this article about automatic dependency injection in Spring:
https://www.baeldung.com/spring-autowire
You missed the autowiring annotation in the controller to inject the service which may make this.peopleService to be null.
#Autowired
private PeopleService peopleService;
You also need to do autowire in your serviceimpl class
#Autowired
private PeopleRepository peopleRepository;

Parameter 0 of constructor in .... Spring Boot

I am a fish in Spring Boot and Data Jpa, I Tried to create a basic Spring boot application but every time I am encountering the error. Can you help me?
That's my code:
Spring Boot Application class:
#SpringBootApplication
#ComponentScan(basePackages = "com.project.*")
#EnableJpaRepositories(basePackages = "com.project.repository.*")
#EntityScan(basePackages = "com.project.entities.*")
#EnableAutoConfiguration
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
Controller Class:
#RestController
#RequestMapping(value = "/api")
public class controller {
private IUserServices userServices;
#Autowired
public controller(IUserServices userServices) {
this.userServices = userServices;
}
#GetMapping(value = "/merhaba")
public String sayHello(){
return "Hello World";
}
#GetMapping(value = "/getall")
public List<User> getAll(){
return this.userServices.getAllUsers();
}
}
Repository Class:
#Repository
public interface UserRepository extends JpaRepository<User,Long> {
}
IServices Class:
#Service
public interface IUserServices {
void saveUser(User user);
List<User> getAllUsers();
}
ServicesImpl Class:
#Service
public class UserServicesImpl implements IUserServices{
private UserRepository userRepository;
#Autowired
public UserServicesImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public void saveUser(User user) {
this.userRepository.save(user);
}
#Override
public List<User> getAllUsers() {
return this.userRepository.findAll();
}
}
Entity Class:
#Entity
#Table(catalog = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
#Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
AND THIS MY ERROR MESSAGE:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.project.services.UserServicesImpl required a bean of
type 'com.project.repository.UserRepository' that could not be found.
Action:
Consider defining a bean of type 'com.project.repository.UserRepository' in your
configuration.
Process finished with exit code 0
SO This is application properties file:
spring.jpa.properties.hibernate.dialect =
org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.show-sql=true
spring.datasource.url=jdbc:postgresql://localhost:5432/u
spring.datasource.username=postgres
spring.datasource.password=1234
spring.jpa.properties.javax.persistence.validation.mode = none
There are some issues that you should fix them.
First
When you have the spring boot application with #SpringBootApplication you don't need other stuff such as #EnableAutoConfiguration and etc, So remove them all.
You can read more about it here.
Second
You don't need to annotate your service interface with #Service, because you did it in the UserServicesImpl class.
Third
You defined id as an integer in your user entity but in the repository, you wrote your id as Long. It's wrong. It should be something like this.
#Repository
public interface UserRepository extends JpaRepository<User,Integer> {
}
Try the above solutions and let me know the result.

Java Spring Boot: Dependency Injection error: Change 1st parameter of abstract method to Optional

I am trying to use dependency injection in Java Spring Boot. Receiving Error below in controller in this line. productService.updateProduct(product);
Error: Change 1st parameter of abstract method from Product to Optional
How can this be resolved?
public class Product {
#Getter #Setter public #Id #GeneratedValue Long productId;
#Getter #Setter public String productName;
#Getter #Setter public String productDescription;
Product() {}
Product(String productName, String productDescription) {
this.productName = productName;
this.productDescription = productDescription;
}
}
Interface:
public interface IProductService {
public Product updateProduct(Product product);
}
Service:
#Service
public class ProductService implements IProductService {
#Override
public Product updateProduct(Product product){
product.productName = "test12345";
return product;
}
}
Controller:
class ProductController {
ProductRepository repository;
#Autowired IProductService productService;
ProductController(IProductService productService, ProductRepository repository) {
this.productService = productService;
this.repository = repository;
}
#GetMapping("/products/{id}")
Product one(#PathVariable Long id) {
var product = repository.findById(id);
var finalProduct = productService.updateProduct(product); // error in this line
return finalProduct;
}
And check whether your Repository class return Optional<Product>. because findbyId return type of optional. Then your have to use like below.
Optional<Product> product = repository.findById(id);
And Better to add #Autowire #Controller annotation no need constructor.
#Controller
class ProductController {
#Autowired
private ProductRepository repository;
#Autowire
private IProductService productService;
}

AuditingEntityListener junit cannot find context

I have an entity and would like to implement Audit and AuditHistory, both works but while unit testing Application context is null.
The Entity
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
#Entity
#EntityListeners(UserListener.class)
public class User extends BaseModel<String> {
#Column
private String username;
#Column
private String password;
#Transient
private String passwordConfirm;
#ManyToMany
private Set<Role> roles;
}
UserListener
public class UserListener {
#PrePersist
public void prePersist(User target) {
perform(target, INSERTED);
}
#PreUpdate
public void preUpdate(User target) {
perform(target, UPDATED);
}
#PreRemove
public void preRemove(User target) {
perform(target, DELETED);
}
#Transactional(MANDATORY)
void perform(User target, Action action) {
EntityManager entityManager = BeanUtil.getBean(EntityManager.class);
if(target.isActive()){
entityManager.persist(new UserAuditHistory(target, action));
}else{
entityManager.persist(new UserAuditHistory(target, DELETED));
}
}
}
UserAuditHistory
#Entity
#EntityListeners(AuditingEntityListener.class)
public class UserAuditHistory {
#Id
#GeneratedValue
private Long id;
#ManyToOne
#JoinColumn(name = "user_id", foreignKey = #ForeignKey(name = "FK_user_history"))
private User user;
#CreatedBy
private String modifiedBy;
#CreatedDate
#Temporal(TIMESTAMP)
private Date modifiedDate;
#Enumerated(STRING)
private Action action;
public UserAuditHistory() {
}
public UserAuditHistory(User user, Action action) {
this.user = user;
this.action = action;
}
}
BeanUtil for getting and setting context
#Service
public class BeanUtil implements ApplicationContextAware {
private static ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <T> T getBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
}
Now the Junit where I get null pointer exception on the context from the above BeanUtil class in getBean() method.
#RunWith(SpringRunner.class)
#DataJpaTest
public class UserRepositoryTest{
#Autowired
private TestEntityManager entityManager;
#Autowired
private UserRepository repository;
#Test
public void whenFindAll_theReturnListSize(){
entityManager.persist(new User("jk", "password", "password2", null));
assertEquals(repository.findAll().size(), 1);
}
}
This is how I solved the problem, in the test class
#Autowired
ApplicationContext context;
inside the test method called
BeanUtil beanUtil = new BeanUtil();
beanUtil.setApplicationContext(context);
and it worked.
The problem is, that you're not using spring's AOP, but the static context:
private static ApplicationContext context;
It's null, because not creating #Bean leads to unproxied objects. The solution would be to #Autowire it.

Spring boot, does not create beans #Controller, #Service

This is my project directory structure.
All controller and other classes and directories, which are beans, are under the "WebPortalApplication" class, and as Spring Boot doc states, we do not explicitly specify the package to scan for beans, whenever those packages locate unther the "main" class directory, right?
So when I run the "WebPortalApplication" file, it builds, but with such exceptions.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userRestController': Unsatisfied dependency expressed through field 'userService';
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'roleRepository';
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'roleRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException:
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.epam.webPortal.model.Role
#RestController
public class UserRestController {
#Autowired
UserService userService;
private static final Logger LOGGER = LoggerFactory.getLogger(UserRestController.class);
//-------------------Retrieve All Users--------------------------------------------------------
#RequestMapping(value = "/user/", method = RequestMethod.GET)
public String listAllUsers() {
String userAsJson = "";
List<User> users = userService.findAllUsers();
try {
userAsJson = JsonConvertor.toJson(users);
} catch (Exception ex) {
LOGGER.error("Something went wrong during converting json format");
}
LOGGER.info("displaying all users in json format");
return userAsJson;
}
package com.epam.webPortal.service.user;
import com.epam.webPortal.model.User;
import com.epam.webPortal.repository.role.RoleRepository;
import com.epam.webPortal.repository.user.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional
import java.util.Date;
import java.util.HashSet;
import java.util.List;
#Service("userService")
#Transactional
public class UserServiceImpl implements UserService {
private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
#Autowired
private UserRepository userRepository;
#Autowired
private RoleRepository roleRepository;
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Override
public void saveUser(User user) {
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
user.setRoles(new HashSet<>(roleRepository.findAll()));
user.setDateRegistered(new Date());
userRepository.save(user);
LOGGER.info("user with username {} successfully saved", user.getUsername());
}
#Override
public User findByUsername(String username) {
return userRepository.findByUsername(username);
}
#Override
public List<User> findAllUsers() {
return userRepository.findAllUsers();
}
#Override
public User findById(Long Id) {
return userRepository.findById(Id);
}
#Override
public void updateUser(User user) {
final User entity = userRepository.findById(user.getId());
if (entity != null) {
entity.setFirstName(user.getFirstName());
entity.setLastName(user.getLastName());
entity.setEmail(user.getEmail());
entity.setSkypeID(user.getSkypeID());
entity.setDateRegistered(new Date());
entity.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
userRepository.save(entity);
LOGGER.info("user with id {} successfully updated", user.getId());
}
}
#Override
public void deleteUserById(Long id) {
userRepository.deleteById(id);
LOGGER.info("user with id {} successfully deleted", id);
}
}
package com.epam.webPortal.model;
import javax.persistence.*;
import java.util.Set;
#Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#ManyToMany(mappedBy = "roles", fetch = FetchType.EAGER)
private Set<User> users;
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 Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
It looks like you're using JPA.
All JPA entities must be annotated with #Entity.
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.epam.webPortal.model.Role
means, Role class is missing #Entity annotation.
Have you enabled your repos?
#SpringBootApplication
#EnableJpaRepositories
public class WebPortalApplication {
public static void main(String[] args) {
SpringApplication.run(WebPortalApplication.class, args);
}
}
I expect below definition on your RoleRepository; sharing this file will help to further analyze on what is missing.
public interface RoleRepository implements CrudRepository<Role, Long> {
...
}

Categories

Resources