I'm trying to implement Spring AOP in multiple layers application and make advice for #Service and #Controller classes.
Everything works fine without aspect class. When I add that part of code it causes Spring configuration problem.
#Aspect class:
#Aspect
#Component
public class ApplicationMonitor {
private static final Logger logger = Logger.getLogger(ApplicationMonitor.class);
#Pointcut(value = "execution(* hr.mycompany.controller.impl.MyCompanyController.update(*)) && args(obj)")
public void updateMC(Object obj){}
#Before(value="updateMC(obj)")
public void beforeUpdateMC(JoinPoint jp, Object obj) {
Object obj = jp.getArgs()[0];
logger.info("beforeUpdateMC " + obj);
}
}
Spring XML aspect configuration:
<aop:aspectj-autoproxy proxy-target-class="true"/>
Application #Controller and #Service classes:
#Controller
public class MyCompanyController implements IMyCompanyController{
#Autowired
private IMyComapnyService myCompanyService;
}
#Service
public class MyCompanyService implements IMyComapnyService {
#Autowired
private IGenericHibernateDao<Object, Integer> vwObjectDao;
}
Error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [hr.mycompany.dao.IGenericHibernateDao] 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)}
09:11:27,871 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/BasicData-portlet]] (http--0.0.0.0-8083-2) StandardWrapper.Throwable: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MyCompanyService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private hr.mycompany.dao.IGenericHibernateDao hr.mycompany.services.impl.MyCompanyService.vwObjectDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [hr.mycompany.dao.IGenericHibernateDao] 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)}
Where the problem is?
EDIT:
Part of class with Hibernate methods:
#Transactional(readOnly = true)
public abstract class GenericHibernateDao<T, PK extends Serializable> implements IGenericHibernateDao<T, PK> {
private static final Logger log = LoggerFactory.getLogger(GenericHibernateDao.class);
#Autowired
#Qualifier(value = "hibernateSessionFactory")
protected SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
#SuppressWarnings("unchecked")
#Transactional(readOnly = false)
public PK save(T entity) {
Assert.notNull(entity, "Argument entity cannot be null in a call to GenericHibernateDao.save !");
Session session = getSessionFactory().getCurrentSession();
return (PK) session.save(entity);
}
...
}
EDIT (22-02-2019):
When I change this line of code:
<aop:aspectj-autoproxy proxy-target-class="true"/>
like this:
<aop:aspectj-autoproxy />
Error disapears, but aspect does not work.
I found solution.
I change this line of code in Spring XML config file:
<aop:aspectj-autoproxy proxy-target-class="true"/>
I set proxy-target-class to false:
<aop:aspectj-autoproxy proxy-target-class="false"/>
I deleted this dependency from pom.xml file:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
I set the same spring-aop vesion like Spring version I use in Spring XML config file.
I changed this:
http://www.springframework.org/schema/aop/spring-aop.xsd
like this:
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
Related
In tests i can add any bean (using static nested configuration class). but how can i add spring-data repositories? i can't return then as new bean because i can't instantiate them - they are interfaces
#RunWith(SpringRunner.class)
#DataMongoTest
//#SpringBootTest // or this annotation
public class JTest {
#Configuration
static class Config {
static class TestEntity {
String id;
}
interface TestRepository extends ReactiveMongoRepository<TestEntity, String> {}
}
#Autowired Config.TestRepository testRepository;
#Test
public void test() {}
}
running with #DataMongoTest gives me
Caused by: java.lang.IllegalStateException: Unable to retrieve #EnableAutoConfiguration base packages
running with #SpringBootTest gives:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'xxx.JTest$Config$TestRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
how can i add new repositories in tests?
Spring doesn't pick up nested interface repository (and instantiate a bean) by default. To enable, see:
#RunWith(SpringRunner.class)
#DataMongoTest
#EnableMongoRepositories(considerNestedRepositories = true)
public class JobTest {
#TestConfiguration
static class Config {
static class TestEntity {
String id;
}
....
Internally, Spring registers a bean with new SimpleMongoRepository<T, ID>(..) if none other specified.
Edit
Just realized you are using reactive Mongo. So switch to EnableReactiveMongoRepositories(..) instead.
I'm migrating from spring-data-neo4j version 4.1 to 4.2.
On the application startup I'm getting an error:
Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.neo4j.ogm.session.Session' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
repository.ActivityRecordRepository.java:
public interface ActivityRecordRepository extends GraphRepository<ActivityRecord>, ActivityRecordRepositoryCustom {}
repository.ActivityRecordRepositoryCustom.java:
public interface ActivityRecordRepositoryCustom {
...
}
repository.impl.ActivityRecordRepositoryImpl.java:
public class ActivityRecordRepositoryImpl implements ActivityRecordRepositoryCustom {
private final Session session;
public ActivityRecordRepositoryImpl(Session session) {
this.session = session;
}
....
}
My configuration:
#ComponentScan
#Configuration
#EnableNeo4jRepositories("com.example.repository")
#EnableTransactionManagement
public class ApplicationConfiguration {
....
#Bean
public EventListener eventListener() {
return new CustomEventListener();
}
#Bean
public SessionFactory getSessionFactory() {
final SessionFactory sessionFactory = new SessionFactory(databaseConfiguration, "com.example.entity");
sessionFactory.register(eventListener());
return sessionFactory;
}
}
How to properly autowire session object to custom repository implementation?
I'm using:
Spring Version: 4.3.2.RELEASE
Spring Data Neo4j Version: 4.2.11.RELEASE
I Create the bean by configuration with out name
#Configuration
#ConfigurationProperties(prefix = "mysql")
public class DbConfiguration extends BaseDbConfiguration {
#Bean//(name = "fix")
#Override
public DbClient createClient() {
return super.createClient();
}
}
usage:
#Autowired
private DbClient dbClient;
when I running application it can't start up
And throw NoSuchBeanDefinitionException:
No qualifying bean of type [DbClient] 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)}
But I fix it by add name, why??
#Bean(name = "fix")
I also add a test such like this:
public class TestCreate {
#NotNull
private int test;
public Test createTest() {
return new Test(this.test);
}
}
it configuration like this:
#Configuration
#ConfigurationProperties(prefix = "test")
public class TestConfiguration extends TestCreate {
#Override
#Bean
public Test createTest() {
return super.createTest();
}
}
And autowired like this:
#Autowired
private Test test;
However, this test may work well
It also create Bean without name and Autowired with out Qualifier
Please Tell me why....thanks
Sorry.
I have found the results:
Overriding bean definition for bean 'createClient': replacing ...
So Spring-Boot will create Bean by FunctionName rather than returning ObjectName.
I'm trying to autowire an interface inside a controller bean
In my context configuration file I've put
<context:annotation-config />
and
<bean id="viewVerbale" class="com.sirfe.controller.VerbaliController" />
my controller class is
#Controller
public class VerbaliController {
#Autowired
VerbaliRepository repository;
private static final Logger logger = LoggerFactory.getLogger(VerbaliController.class);
#RequestMapping(value = "/sirfe/verbale/{sequVerbale:.+}", method = RequestMethod.GET)
public ModelAndView viewVerbale(#PathVariable("sequVerbale") String sequVerbale) {
logger.debug("welcome() - sequVerbale {}", sequVerbale);
Verbali verbale = repository.findOne(Long.parseLong(sequVerbale));
ModelAndView model = new ModelAndView();
model.setViewName("sirfe/verbali/viewVerbale");
model.addObject("sequVerbale", sequVerbale);
return model;
}
}
my interface signature is
public interface VerbaliRepository extends CrudRepository<Verbali, Long> { }
and when I launch my app I get
Could not autowire field: com.sirfe.repository.VerbaliRepository com.sirfe.controller.VerbaliController.repository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.sirfe.repository.VerbaliRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
Looks like you're trying to use Spring JPA repository.
In order to have Spring create bean for your repository interfaces, you need in applicationContext.xml to declare what package to scan
<jpa:repositories base-package="com.sirfe.repository" />
Doing so, Spring will generate bean implementing the interface for you.
See Spring JPA Repositories
Spring is complaining that it cannot find a valid bean definition that matches, ie there is no bean defined that is an implementation of VerbaliRepository.
You need to define a bean or alternatively annotate an implementation class with #Component eg
<bean id="myRepository" class="com.foo.bar.MyRepository" />
or
#Component
public class MyRepository implements VerbaliRepository {
....
}
Application-Context is correctly setup!
Heres my class scenario
public interface IManager
{
public void doStuff();
}
#Component
public abstract class ManagerAction implements IManager
{
#Async
#Override
public void doStuff()
{
//doing stuff
}
public abstract manageWorker();
}
#Component
public class Working extends ManagerAction
{
#Override
public manageWorker()
{
//some busy code
}
}
#Component
public class NotWorking extends ManagerAction
{
#Override
public manageWorker()
{
//some busy code
}
}
#Service
public class BusinessWorker
{
#Autowire
private IManager manager_;
public void preformTasks()
{
manager_.doStuff();
}
}
Heres my error
ERROR [main] (ContextLoader.java:307) - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'BusinessWorker': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.B
eanCreationException: Could not autowire field: private com.background.IManager com.background.BusinessWorker.manager_; nested exception is org.springframework.beans.
factory.NoSuchBeanDefinitionException: No matching bean of type [com.background.IManager] 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)}
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.background.IManager com.background.BusinessWorker.manager_;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.background.IManager] 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)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
... 28 more
Application-Context
<mvc:annotation-driven />
<task:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.background" />
The error message says it all: you try to autowire an instance of IManager, but two different Spring components implement this interface, so Spring doesn't know which one to autowire. You need to use the #Qualifier annotation to specify which one you want Spring to autowire.