Error in running sample Spring annotation based program without any xml - spring

Hi I am trying to run a simple spring annotation based program without using any xml based configuration. I'm getting the error "Unsatisfied dependency expressed through field".
I learnt that using #ComponentScan spring scans the package mentioned and look for beans annotated.
Putting the code herein. My project is a maven project with hierarchy like MyProject/src/java/SpringAnnotnDemo/autowireAnnotationBased
There are three classed
Department.java
Employee.java
MainClass.java --> The main class
Department.java
package SpringAnnotnDemo.autowireAnnotationBased;
import org.springframework.stereotype.Component;
#Component
public class Department {
private String department;
public String getDeptName() {
return department;
}
public void setDeptName(String deptName) {
this.department = deptName;
}
}
Employee.java
package SpringAnnotnDemo.autowireAnnotationBased;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class Employee {
private int eid;
private String ename;
#Autowired
private Department department;
public int getEid() {
return eid;
}
public void setEid(int eid) {
this.eid = eid;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public void showEployeeDetails() {
System.out.println("Employee Id : " + eid);
System.out.println("Employee Name : " + ename);
department.setDeptName("Mechanical Engineering");
System.out.println("Department : " + department.getDeptName());
}
}
MainClass.java
package SpringAnnotnDemo.autowireAnnotationBased;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan("SpringAnnotnDemo.autowireAnnotationBased")
public class MainClass {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(Employee.class);
Employee emp = ctx.getBean(Employee.class);
emp.setEid(374);
emp.setEname("S.C.B");
emp.showEployeeDetails();
}
}
On running this simple program I am getting an error as below.
`Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'employee': Unsatisfied dependency expressed through field 'department'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'SpringAnnotnDemo.autowireAnnotationBased.Department' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}`
Can anyone please help me figure out what am I missing. I want the most simplest form of using annotation based spring without using any xml based configuration.

Change your this line
ApplicationContext ctx = new AnnotationConfigApplicationContext(Employee.class);
to this line
ApplicationContext ctx = new AnnotationConfigApplicationContext(MainClass.class);

Related

Failed to create bean

I tried to run the following test code:
package guru.springframework.test.external.props;
import guru.springframework.test.jms.FakeJmsBroker;
import guru.test.config.external.props.ExternalPropsEnvironment;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertEquals;
/**
* Created by jt on 5/7/16.
*/
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = ExternalPropsEnvironment.class)
public class PropertySourceEnvTest {
#Autowired
FakeJmsBroker fakeJmsBroker;
#Test
public void testPropsSet() throws Exception {
assertEquals("10.10.10.123", fakeJmsBroker.getUrl());
assertEquals(3330, fakeJmsBroker.getPort().intValue());
assertEquals("Ron", fakeJmsBroker.getUser());
assertEquals("Burgundy", fakeJmsBroker.getPassword());
}
}
Not sure why I am getting this error:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: guru.springframework.test.jms.FakeJmsBroker guru.springframework.test.external.props.PropertySourceEnvTest.fakeJmsBroker; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [guru.springframework.test.jms.FakeJmsBroker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
FakeJmsBroker.java:
package guru.springframework.test.jms;
/**
* Created by jt on 5/7/16.
*/
public class FakeJmsBroker {
private String url;
private Integer port;
private String user;
private String password;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
In this instance, FakeJmsBroker is just a POJO. Unless you either annotate it as #Component, #Service, etc, then Spring knows nothing about it.
You can also return a new instance of this as a #Bean in a #Configuration class. However, looking at this class, unless it's holding properties, it doesn't make sense as a component as it doesn't contain any behavior. Here's an example of making it a bean from a configuration.
#Configuration
public class MyConfig {
// This will create an instance of FakeJmsBroker that will be in the Spring context
#Bean
public FakeJmsBroker createFakeBroker() {
return new FakeJmsBroker();
}
}
Either that class/method, or using the annotation-driven approach will make this bean eligible for autowiring.

NullPointerException of JDBC Template in DAO Constructor

I am new to Spring Boot and was trying to implement the below code for Spring Boot JDBC. I am getting a NullPointerException in the this.jdbcTemplate in the UserDao constructor while running the application. I think the error is because the UserDao constructor is being called before the instantiation of JdbcTemplate. Is that correct?
I haven't come across this error until now where the #Autowired cannot resolve the dependencies. Can someone please elaborate upon the reason for the error?
SpringBootDatabaseApplication.java
package com.mrityu.springbootdatabase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringBootDatabaseApplication {
#Autowired
private UserDao userDao;
public static void main(String[] args) {
SpringApplication.run(SpringBootDatabaseApplication.class, args);
}
}
UserDao.java
package com.mrityu.springbootdatabase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
#Repository
public class UserDao {
#Autowired
private JdbcTemplate jdbcTemplate;
public UserDao() {
String query = "create table if not exists User(id int primary key, name varchar(200))";
int update = this.jdbcTemplate.update(query);
System.out.println("Constructor Called: " + update);
}
}
I didn't try to run the code, but you're trying to use the uninitialized jdbcTemplate field in your constructor.
Constructor base injection should do the trick
public UserDao(JdbcTemplate jdbcTemplate) {...}
Otherwise, you can still use field injection and move your logic into a method.
public void yourMethod() {
String query = "create table if not exists User(id int primary key, name varchar(200))";
int update = this.jdbcTemplate.update(query);
System.out.println("Method Called: " + update);
}
In your case, it's about how java initializes classes, not spring boot auto wiring.
You can check this answer for the dependency injection precedence.

No qualifying bean of type 'testgroup.private_clinic.dao.PatientDAO' available in SpringBoot Application

I'm developing crud application, and experiencing difficulties with springboot, which fails on startup. This is what i got:
20764 WARNING [main] --- org.springframework.context.annotation.AnnotationConfigApplicationContext: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'patientServiceImpl': Unsatisfied dependency expressed through method 'setPatientDAO' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'testgroup.private_clinic.dao.PatientDAO' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Screenshot of project structure:
Model:
package testgroup.private_clinic.model;
import javax.persistence.*;
#Entity
#Table(name="Patients")
public class Patient {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
int id;
#Column(name="patient_name")
String name;
#Column(name = "patient_surname")
String surname;
#Column(name = "patient_patronimic")
String patronimic;
#Column(name="adress")
String adress;
#Column(name = "status")
String status;
#Column(name="diagnosis")
String diagnosis;
//+getters and setters
Controller:
package testgroup.private_clinic.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import testgroup.private_clinic.model.Patient;
import testgroup.private_clinic.service.PatientService;
import java.util.List;
#RestController
public class PatientController {
PatientService patientService;
#Autowired
public void setPatientService(PatientService patientService){
this.patientService = patientService;
}
#RequestMapping(method = RequestMethod.GET)
public ModelAndView allPatients(){
List<Patient> patients = patientService.allPatients();
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("patients");
modelAndView.addObject("patientList", patients);
return modelAndView;
}
#RequestMapping(value= "/edit{id}", method = RequestMethod.GET)
public ModelAndView editPage(#PathVariable("id") int id){
Patient patient = patientService.getByID(id);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("editPage");
modelAndView.addObject("patient", patient);
return modelAndView;
}
#RequestMapping(value="/edit", method = RequestMethod.POST)
public ModelAndView editPatient(#ModelAttribute("patient") Patient patient){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("redirect:/");
patientService.edit(patient);
return modelAndView;
}
}
Repository:
package testgroup.private_clinic.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import testgroup.private_clinic.model.Patient;
import javax.transaction.Transactional;
import java.util.*;
#Repository
public class PatientDAOImpl implements PatientDAO {
SessionFactory sessionFactory;
#Autowired
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
#Override
#Transactional
public List<Patient> allPatients() {
Session session = sessionFactory.getCurrentSession();
return session.createQuery("from Patient").list();
}
#Override
#Transactional
public void add(Patient patient) {
Session session = sessionFactory.getCurrentSession();
session.persist(patient);
}
#Override
#Transactional
public void delete(Patient patient) {
Session session = sessionFactory.getCurrentSession();
session.delete(patient);
}
#Override
#Transactional
public void edit(Patient patient) {
Session session = sessionFactory.getCurrentSession();
session.update(patient);
}
#Override
#Transactional
public Patient getByID(int id) {
Session session = sessionFactory.getCurrentSession();
return session.get(Patient.class, id);
}
}
Service:
package testgroup.private_clinic.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import testgroup.private_clinic.model.Patient;
import testgroup.private_clinic.dao.PatientDAO;
import javax.transaction.Transactional;
import java.util.List;
#Service
public class PatientServiceImpl implements PatientService{
PatientDAO patientDAO;
#Autowired
public void setPatientDAO(PatientDAO patientDAO){
this.patientDAO = patientDAO;
}
#Transactional
#Override
public List<Patient> allPatients() {
return patientDAO.allPatients();
}
#Transactional
#Override
public void add(Patient patient) {
patientDAO.add(patient);
}
#Transactional
#Override
public void delete(Patient patient) {
patientDAO.delete(patient);
}
#Transactional
#Override
public void edit(Patient patient) {
patientDAO.edit(patient);
}
#Transactional
#Override
public Patient getByID(int id) {
return patientDAO.getByID(id);
}
}
Main class:
package testgroup.private_clinic.service;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringBootClass {
public static void main(String[] args){
SpringApplication.run(testgroup.private_clinic.service.SpringBootClass.class, args);
}
}
Spring Boot uses classpath component scanning meaning, your entry-point class which is SpringBootClass will scan for all beans within its class path unless you configure it not to.
Looking into your project structure, SpringBootClass is under the testgroup.private_clinic.service package thus Spring Boot will only scan this package for beans and it only found the PatientServiceImpl however, before it injects this to the application context, it will need to inject first its dependency PatientDAO which is not part of the testgroup.private_clinic.service package thus, explains your error.
You have two options to fix this:
Move your SpringBootClass to the base package testgroup.private_clinic - this will make Spring Boot scan on all you components under this package and its sub-packages (e.g., service, dao)
Use #ComponentScan on your SpringBootClass and define there the base package you want to scan for beans.
#ComponentScan(basePackages = "testgroup.private_clinic")
Thanks and cheers!

java.lang.IllegalArgumentException: Not a managed type: class while initiating repository bean

Hi I am trying to load some database values at start time of spring boot application. I have autowired service, and in service i have autowired Dao. Below is the error.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'validationExpressionService': Unsatisfied dependency expressed through field 'validationExpressionDao'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'IValidationExpressionDao': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.ril.nfg.dao.bean.ValidationExpression
I have added #EnitityScan #EnableJPARepository
FYI, Primary key in the case in String, hope that is ok.
Entity
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* The Class ValidationExpression.
*/
package com.ril.nfg.dao.bean;
#Entity
#Table(name = "VALIDATION_EXPRESSION")
public class ValidationExpression implements Serializable {
private static final long serialVersionUID = 9096950800262493651L;
private String validationId;
private String expression;
private String createdBy;
private Date createdOn;
private String description;
private String responseCode;
#Id
#Column(name = "VALIDATION_ID", nullable = false, length = 100)
public String getValidationId() {
return validationId;
}
public void setValidationId(String validationId) {
this.validationId = validationId;
}
#Column(name = "EXPRESSION", nullable = false, length = 200)
public String getExpression() {
return expression;
}
public void setExpression(String expression) {
this.expression = expression;
}
//remaining getters and setters
}
Repository
package com.ril.nfg.dao.repos;
import com.ril.nfg.dao.bean.ValidationExpression;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* The Interface IValidationExpressionDao.
*/
#Repository
public interface IValidationExpressionDao extends JpaRepository<ValidationExpression, String> {
}
Service
import java.util.List;
#Service
public class ValidationExpressionService {
#Autowired
IValidationExpressionDao validationExpressionDao;
public List<ValidationExpression> getAll() {
return validationExpressionDao.findAll();
}
}
Class with #Autwired Service
public class CacheModuleParam implements ApplicationContextAware{
private static List<ValidationExpression> validationExpressionList = null;
#Autowired
ValidationExpressionService validationExpressionService;
#Override
public void setApplicationContext(final ApplicationContext appContext) throws BeansException {
validationExpressionList = validationExpressionService.getAll();
}
}
Application Class
#ComponentScan(basePackages = {"com.ril.nfg"})
#EnableWebMvc
#EnableAutoConfiguration
#SpringBootApplication//(exclude={DataSourceAutoConfiguration.class})
#EnableJpaRepositories(basePackages="com.ril.nfg.dao.repos",entityManagerFactoryRef="oracleEntityManagerFactory")
//#EntityScan(basePackages = "com.ril.nfg.dao.bean")
public class NFGApplication {
public static void main(String[] args) {
SpringApplication.run(NFGApplication.class, args);
}
}
All solutions on internet focuses on #EntityScan. Please help me understand what is wrong with this code. Thanks in advance
Why do you have all this configuration? Simply put our application in the package tree one level above all the other classes and you can go with a class like this:
#SpringBootApplication
public class NFGApplication {
public static void main(String[] args) {
SpringApplication.run(NFGApplication.class, args);
}
}
Packages:
com.ril.nfg <- here you put NFGApplication
And all other classes in subpackages of com.ril.nfg
And then everything will work!

Unsatisfied dependency expressed through field - Springboot the Application, the component and the test class are all in the same package

My understanding is that the SpringBootApplication annotation includes
ComponentScan
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-using-springbootapplication-annotation.html
The bean is discovered and printed in Application.main(), why does the unit test not find it?
This unit test fails with:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.pds.pdssr.etlfile.EtlFileServicesTest': Unsatisfied dependency expressed through field 'etlFileServices'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.pds.pdssr.etlfile.EtlFileServices' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
With the appropriate level of debug, i.e "org.springframework.context.annotation"="debug" I can see that the bean was discovered during component scanning.
Nevertheless, the unit test results in:
[ERROR] getAll(com.pds.pdssr.etlfile.EtlFileServicesTest) Time elapsed: 0.007 s <<< ERROR!
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.pds.pdssr.etlfile.EtlFileServicesTest': Unsatisfied dependency expressed through field 'etlFileServices'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.pds.pdssr.etlfile.EtlFileServices' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.pds.pdssr.etlfile.EtlFileServices' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
The Application:
package com.pds.pdssr.bootstrap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
//#EnableJpaRepositories("com.pds.pdsssr.jpa")
#SpringBootApplication
// #EntityScan("com.pds.pdssr.models")
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(Application.class, args);
for (String name : applicationContext.getBeanDefinitionNames()) {
logger.info("bean: " + name);
}
}
}
The Component:
package com.pds.pdssr.bootstrap;
import java.util.List;
import javax.persistence.EntityManagerFactory;
import javax.transaction.Transactional;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.pds.pdssr.models.EtlFile;
#Repository
public class EtlFileServices {
#Autowired
private static EntityManagerFactory entityManagerFactory;
public SessionFactory getSessionFactory() {
SessionFactory sessionFactory = null;
if (entityManagerFactory == null) {
throw new IllegalStateException("entityManagerFactory is null");
}
sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
if (sessionFactory == null) {
throw new NullPointerException("factory is not a hibernate factory");
}
return sessionFactory;
}
#SuppressWarnings("unchecked")
public List<EtlFile> getAll() {
return getAll("etlFile",getSessionFactory().getCurrentSession());
}
#SuppressWarnings("rawtypes")
protected List getAll(String tableName, Session session) {
String queryText = "from " + tableName;
return getList(tableName, queryText, session);
}
#SuppressWarnings("rawtypes")
protected List getList(String tableName, String queryText, Session session) {
long start = System.nanoTime();
Query query = session.createQuery(queryText);
List result = query.list();
long end = System.nanoTime();
long millis = (end - start) / 1000000;
//logger.debug("table: " + tableName + " millis " + millis + " rows: " + result.size());
return result;
}
}
The test class:
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringRunner;
import com.pds.pdssr.bootstrap.EtlFileServices;
import com.pds.pdssr.models.EtlFile;
#RunWith(SpringRunner.class)
public class EtlFileServicesTest {
#Autowired
private EtlFileServices etlFileServices;
#Test
public void getAll() {
List<EtlFile> etlFiles = etlFileServices.getAll();
assertNotNull(etlFiles);
}
}
Original answer:
You need to have
#RunWith(SpringRunner.class)
#SpringBootTest(classes = YourMainClass.class)
in your test class(es).
Further answer based on comment
If you really want to have SessionFactory in your project, you need to tell spring framework to have SessionContext explicitly. It can be done by add
spring.jpa.properties.hibernate.current_session_context_class = org.springframework.orm.hibernate5.SpringSessionContext
to your configuration file. Here's a working example for your problem.
HTH

Resources