this is my code:
my model class:
#Entity
#Table(name="admin")
public class Admin extends Profile{
public Admin(){}
public Admin(String mail, String name, String lastName, String password, Date birthDate, int gsm){
super(mail, name, lastName, password, birthDate, gsm);
}
}
the DAO class:
#Repository
public class AdminDAO {
private static final Logger logger = LoggerFactory.getLogger(AdminDAO.class);
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
this.sessionFactory = sf;
}
#SuppressWarnings("unchecked")
public List<Admin> listAdmins() {
Session session = this.sessionFactory.getCurrentSession();
List<Admin> adminsList = session.createQuery("from Admin").list();
for(Admin a : adminsList){
logger.info("Admin List::"+a);
}
return adminsList;
}
}
my Service class:
#Service
public class AdminService {
#Autowired
private AdminDAO adminDAO;
public void setAdminDAO(AdminDAO adminDAO) {
this.adminDAO = adminDAO;
}
#Transactional
public List<Admin> listAdmins() {
return this.adminDAO.listAdmins();
}
}
when i run my code i get this error message:
java.lang.NullPointerException
at com.journaldev.spring.dao.AdminDAO.listAdmins(AdminDAO.java:38)
i added an admin manually in my database, but it still showing the null pointer exception
what i am doing wrong ??
note: i have another class that works fine, it gets all entities and when the database is empty, it doesn't generate null pointer exception
You missed the #Autowired or the #Inject annotation for the setter method for adminDAO. It has to be
#Autowired
public void setAdminDAO(AdminDAO adminDAO) {
this.adminDAO = adminDAO;
}
You have to annotate all dependencies of your Bean with #Autowired or #Inject.
Related
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.
First time using EasyMock and Spring together.
I have the test class:
#RunWith(EasyMockRunner.class)
public class ProjectServiceTest {
#Mock
private ProjectRepository projectRepositoryMock;
#TestSubject
private ProjectService service new ProjectService();
#Before
public void setUp() throws Exception {
Project project = new Project("Project");
EasyMock.expect(projectRepositoryMock.findOne(1)).andReturn(project);
}
#After
public void tearDown() throws Exception {
}
#Test
public void getProjectById() throws Exception {
System.out.println(this.service.getProjectById(1);
}
This is my project entity:
#Entity
#Table(name = "Project")
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String projectName;
public Project(){
}
public Project(String projectName) {
this.projectNaam = projectName;
}
It also has the usual getters and setters.
My repository just extends the JpaRepository.
And this is my ProjectService class
#Service
public class ProjectService {
#Autowired
private ProjectRepository projectRepository;
public ProjectService(){
}
public Project getProjectById(Integer id){
return this.projectRepository.findOne(id);
}
public void saveProject(Project project){
this.projectRepository.save(project);
}
public void deleteProject(Integer id){
this.projectRepository.delete(id);
}
public List<Project> getAllProjects(){
return this.projectRepository.findAll();
}
public Project findProjectById(Integer id){
return this.projectRepository.findOne(id);
}
}
My test failed so that's why I use system.out.println to figure out whats going on. It prints: null.
I don't understand this. #Mock and #TestSubject seems good, becauase I want to test the service and mock the repository.
Instead of
System.out.println(this.service.getProjectById(1);
I tried
System.out.println(this.projectRepositoryMock.findOne(1));
But this also returns null.
You need to put the mock in replay mode. Try
#Before
public void setUp() throws Exception {
Project project = new Project("Project");
EasyMock.expect(projectRepositoryMock.findOne(1)).andReturn(project);
EasyMock.replay(projectRepositoryMock);
}
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> {
...
}
My professor gave a sample Spring MVC ORM project with Hibernate but I can not figure out the sequence of events involved, in particular about the usage of service business object.
This is just a little part of the project, just to make my ideas clearer.
domain:
#Entity
#Table(name = "department")
public class Department implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long uid;
private String name;
#OneToMany(mappedBy="department",cascade=CascadeType.PERSIST)
private List<Employee> employees = new ArrayList<Employee>();
public Department() {
}
public Department(String name) {
this.name = name;
}
// getters, setters, hashcode() and equals(), toString()...
controller:
#Controller
#RequestMapping("/department")
public class DepartmentController {
#Autowired
#Qualifier("departmentBO")
private DepartmentBO departmentBO;
static final Logger logger = Logger.getLogger(DepartmentController.class);
#RequestMapping(value = "/home", method = RequestMethod.GET)
public String departmentHome(Model model) {
logger.debug("department home() invoked");
List<Department> list = departmentBO.findAllDepartments();
model.addAttribute("list", list);
return "departments";
}
// i'll paste just the first controller ;)
business:
public interface DepartmentBO {
public void delete(long uid);
public List<Department> findAllDepartments();
public Department findByUid(Long uid);
public void save(Department department);
public void update(Department department);
}
business/impl:
#Service
#Transactional
public class DepartmentBoImpl implements DepartmentBO {
#Autowired
private DepartmentDAO departmentDao;
static final Logger logger = Logger.getLogger(DepartmentBoImpl.class);
#Override
public void save(Department department) {
departmentDao.save(department);
}
#Override
public void update(Department department) {
departmentDao.update(department);
}
#Override
public void delete(long uid) {
departmentDao.delete(uid);
}
#Override
public List<Department> findAllDepartments() {
return departmentDao.findAllDepartments();
}
#Override
public Department findByUid(Long uid) throws DataAccessException {
return departmentDao.findByUid(uid);
}
}
dao:
public interface DepartmentDAO {
public void delete(long uid);
public List<Department> findAllDepartments();
public Department findByUid(Long uid);
public void save(Department user);
public void update(Department user);
}
dao/impl:
#Repository
public class DepartmentDAOImplSf implements DepartmentDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public void delete(long uid) {
Department department = (Department) sessionFactory.getCurrentSession()
.get(Department.class, uid);
sessionFactory.getCurrentSession().delete(department);
}
#Override
public void save(Department department) {
sessionFactory.getCurrentSession().save(department);
}
#Override
public void update(Department department) {
sessionFactory.getCurrentSession().saveOrUpdate(department);
}
#Override
public List<Department> findAllDepartments() {
List<Department> list = (List<Department>) sessionFactory
.getCurrentSession()
.createQuery("FROM Department").list();
return list;
}
#Override
public Department findByUid(Long uid) {
Department department = (Department) sessionFactory
.getCurrentSession().get(Department.class, uid);
return department;
}
}
I know that the order is: domain model -> controller-> service -> dao ->db, but why use a DepartmentBO? and why DepartmentBoImpl autowired DepartmentDao? Who of them act first? Something that i'm not understanding is messing up my conception of how it works and the sequence of the process..
Thanks for your help ;)
EDIT: "
In few words my question is, what is the sequence of this code? user goes on the /home page that redirect on "departments" page. But what happen before this --> "List list = departmentBO.findAllDepartments();" ?;)
When the departmentBO.findAllDepartments() method is called if you look at the code it invokes the sessionFactory. That is an internal factory class in Hibernate that basically builds a transactional connection to the DB in order to run a query. You are defining the query in the createQuery method and then ultimately executing it with the list() method. These two methods are part of the database session that Hibernate has instantiated.
Departments Page -> departmentBO.findAllDepartments() -> sessionFactory -> createQuery -> list()
Or in pseudo code-ish
Departments Page -> execute findAllDepartments method -> fetch / build a database connection -> define the query -> execute the query -> Return the list!
I have two tables Employee and Address as shown:
public class Employee {
private Integer id;
private String firstName;
private String lastName;
private boolean employeeStatus;
private Address address;
//getters setters
}
public class Address {
private Integer id;
private String country;
private String city;
private String street;
private Integer emp_id;
//getters setters
}
#Repository("employeeDao")
public class EmployeeDaoImpl implements EmployeeDao {
private JdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
#Override
public void insertEmployee(Employee e)
{
String sql = "INSERT INTO tbl_employee (dept_id,firstName,lastName,employeeStatus) values(?,?,?,?,?)";
this.jdbcTemplate.update(sql,new
Object[]{e.getDept_id(),e.getFirstName(),e.getLastName(),e.isEmployeeStatus()});
// INSERT ADDRESS????
}
// Other Methods
}
Now i want to implement Transactional while inserting the employee and address table attributes. I am abit confused here. Does #transactional annotation over the method does the required job? So far i understood that. Also, is it best practice to insert address from where i am inserting employee attributes? I also read somewhere that the transactional should be implemented from service layer than Dao. How would transactional can be implemented in this case?
EDIT
Since it is recommended to use #transactional in service layer, service layer became like:
#Service("employeeService")
#Transactional
public class EmployeeServiceImpl implements EmployeeService{
#Autowired
EmployeeDao employeeDao;
#Autowired
AddressDao addressDao;
#Override
public void insertEmployee(Employee e) {
employeeDao.insertEmployee(e);
addressDao.insertAddress(e.address);
}
}
is it the right way to perform transactional? Also can anyone explain #Transactional(propagation = Propagation.SUPPORTS, readOnly = true) instead of plain #Transactional ?
Alltough the #Transactional annotation would do the job, transactions are usually defined on service level. This way one business call is in one transaction, making sure everything succeeds or fails together.
you can read about #transactional in combination with jdbctemplate here