This question already has an answer here:
Is it possible to set a bean name using annotations in Spring Framework?
(1 answer)
Closed 4 years ago.
I am testing out simple AOP use case in Spring but am getting the below error,
Exception in thread "main"
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
bean named 'bean1' is defined
Below are my source files,
DemoConfig.java
package com.luv2code.aopdemo;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import com.luv2code.aopdemo.aspect.MyDemoLoggingAspect;
import com.luv2code.aopdemo.dao.AccountDAO;
#Configuration
#EnableAspectJAutoProxy
#ComponentScan("com.luv2code.aopdemo")
public class DemoConfig {
#Bean
#Qualifier("bean1")
public AccountDAO accDao() {
return new AccountDAO();
}
#Bean
#Qualifier("bean2")
public MyDemoLoggingAspect myAscpect() {
return new MyDemoLoggingAspect();
}
}
MyDemoLoggingAspect.java
package com.luv2code.aopdemo.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class MyDemoLoggingAspect {
// this is where we add all of our related advices for logging
// let's start with an #Before advice
#Before("execution(** com.luv2code.aopdemo.dao.AccountDAO.addAccount(..))")
public void beforeAddAccountAdvice() {
System.out.println("\n=====>>> Executing #Before advice on addAccount()");
}
}
MainDemoApp.java
package com.luv2code.aopdemo;
import com.luv2code.aopdemo.dao.AccountDAO;
public class MainDemoApp {
public static void main(String[] args) {
// read spring config java class
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoConfig.class);
// get the bean from spring container
AccountDAO theAccountDAO = context.getBean("bean1", AccountDAO.class);
// call the business method
theAccountDAO.addAccount();
// do it again!
System.out.println("\nlet's call it again!\n");
// call the business method again
theAccountDAO.addAccount();
// close the context
context.close();
}
}
I have given my bean ID "bean1", even after that Spring is not able to find my bean in the context. Why am I getting this error and how to resolve this?
The #Qualifier tag is used with the #Autowired annotation.
What you need is
#Bean(name="bean1")
public AccountDAO accDao() {
return new AccountDAO();
}
Related
I need to set properties for SSL to enable HTTPS in my Spring Boot application's main method. My code looks like this:
import com.our.Task.configuration.FileStorageProperties;
import com.our.Task.entities.ApplicationHttpsSettingsEntity;
import com.our.Task.repository.ApplicationHttpsSettingsEntityRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.Properties;
#SpringBootApplication
#EnableConfigurationProperties({FileStorageProperties.class})
public class OurTaskApplication
{
#Autowired
static ApplicationHttpsSettingsEntityRepository applicationHttpsSettingsEntityRepository;
public static void main(String[] args)
{
ApplicationHttpsSettingsEntity applicationsHttpsSettingsEntity = applicationHttpsSettingsEntityRepository.getById(44);
SpringApplication application = new SpringApplication(OurTaskApplication.class);
Properties properties = new Properties();
if (applicationsHttpsSettingsEntity.getUseHttps() > 0)
{
properties.put("server.ssl.key-store", applicationsHttpsSettingsEntity.getKeyStore());
properties.put("server.ssl.key-store-password", applicationsHttpsSettingsEntity.getKeyStorePassword());
properties.put("server.ssl.key-store-type", applicationsHttpsSettingsEntity.getKeyStoreType());
properties.put("server.ssl.key-alias", applicationsHttpsSettingsEntity.getKeyAlias());
}
// SpringApplication.run(OurTaskApplication.class, args);
application.setDefaultProperties(properties);
ConfigurableApplicationContext ctx = application.run(args);
}
}
It gives me warning that #Autowired is not allowed on static methods. When executed it gives null exception.
I have read this
Can't use #Autowired JPA Repository in Main method of Spring Boot application
But it doesn't give any info on how I can do this. I don't want to use properties file.
I wouldn't do something like this in the main method. Let Spring run and then add your configurations.
I would create a runner class that will do whatever I need once the Spring context is set up.
Example:
#Component
#AllArgsConstructor
public class StartRunner implements ApplicationRunner {
/* Add whatever Bean you need here and autowire them through the constructor or with #Autowired */
#Override
public void run(ApplicationArguments args) throws Exception {
// Do whatever you need here inside
}
}
Could you tell me why does a method annotated with #PostContruct runs in my case? As far as I know, a method with #PostContruct is processed by Bean Post Processors. If you want to activate the default CommonAnnotationBeanPostProcessor you need to add <context:annotation-config/> in the XML configuration but I want to use only annotation config. In my case, #ComponentScan in configuration is pointed to the service. It means that only classes from this package candidates to be instantiated.
Configuration class:
package config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan(basePackages = "service")
public class AppConfig {
}
Simple class:
package service;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
#Component
public class Simple {
#PostConstruct
private void sout(){
System.out.println("SOUT");
}
}
And the launcher:
import config.AppConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import service.Simple;
public class Launcher {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
Simple simple = ctx.getBean("simple", Simple.class);
}
}
The output of the app is "SOUT". Could you explain be who invokes the #PostContruct method and how?
AnnotationConfigApplicationContext is an alternative to XML based configurations. When you use it to create objects, it first creates the object and the #Autowired properties, and then calls the #PostConstruct method. It is a handy alternative to writing a setup() or init() method which you would have to call yourself.
AppConfig contains Java Configuration.
package com.wh;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableLoadTimeWeaving;
import org.springframework.context.annotation.EnableLoadTimeWeaving.AspectJWeaving;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.aspectj.EnableSpringConfigured;
#Configuration
#EnableSpringConfigured
#EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
public class AppConfig {
#Bean
#Lazy
public EchoService echoService(){
return new EchoService();
}
#Bean
public InstrumentationLoadTimeWeaver loadTimeWeaver() throws Throwable {
InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
return loadTimeWeaver;
}
}
Service Class
package com.wh;
import org.springframework.stereotype.Service;
#Service
public class EchoService {
public void echo( String s ) {
System.out.println( s );
}
}
EchoDelegateService is the Non Bean class in which we have Autowired The required Bean.
We expect that the EchoService should get autowired.
Problem : EchoService not getting autowired. Gives an Null Pointer exception.
package com.wh;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
#Configurable( preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false )
public class EchoDelegateService {
#Autowired
private EchoService echoService;
public void echo( String s ) {
echoService.echo( s );
}
}
Main Class where we are calling method of NonBean Class.
package com.wh;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
new EchoDelegateService().echo("hihi, it works...");
}
}
Your question already includes the answer: "... in a non-bean class". This simply does not work. All the autowiring, aspect resolving and whatever is to that, only works for beans. Thus, you definitely need to construct your EchoDelegateService via the spring factory:
EchoDelegateService myService = ctx.getBean(EchoDelegateService.class);
myService.echo("this should really work now");
I am learning spring the from book the "Spring in Action fourth edition" by Craig Walls. I am trying to apply advice to the method declared by the interface and I am getting Exception. When I apply the same advice to the class which doesn't implement anything, everything works fine.
Spring version - 4.3.2
Help would be appreciated.
Exception:
Exception in thread "main"org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.fifczan.bean.UserService] is defined
Code:
Interface:
package com.fifczan.bean;
public interface Service {
void doTask();
}
Implementation:
package com.fifczan.bean;
import org.springframework.stereotype.Component;
#Component
public class UserService implements Service {
public void doTask() {
System.out.println("doing task");
}
}
Aspect:
package com.fifczan;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class UserAspect {
//If i change Service(interface) to UserService(implementation)
//in pointcut I am getting the same exception
#Before("execution(* com.fifczan.bean.Service.doTask(..))")
public void userAdvice(){
System.out.println("doing sth before method doTask");
}
}
Configuration:
package com.fifczan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
#Configuration
#EnableAspectJAutoProxy
#ComponentScan
public class AspectJAutoProxyConfig {
}
main :
package com.fifczan;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.fifczan.bean.UserService;
public class AspectJAutoProxyTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AspectJAutoProxyConfig.class);
UserService userService= ctx.getBean(UserService.class);
userService.doTask();
}
}
You're asking for a bean of UserService, which is the concrete class, not the interface. Retrieve or inject a bean of type Service.
I've seen a lot of questions about this error before, but no resolution that works for me.
I'm new to Spring, but trying to use the Spring Data for Neo4J library for a project. I decided to start with a quick spike to make sure I know how everything is working, and so I set up a simple App class with a main method like so:
package org.example.neo4jSpike;
import org.example.neo4jSpike.domain.Actor;
import org.example.neo4jSpike.repositories.ActorRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
/**
* Hello world!
*
*/
#Component
public class App
{
#Autowired
private ActorRepository actors;
#SuppressWarnings("resource")
public static void main( String[] args )
{
ApplicationContext context = new AnnotationConfigApplicationContext(SpikeConfiguration.class);
App a = context.getBean(App.class);
a.init();
}
private void init(){
Actor michaelDouglas = actors.save(new Actor("Michael Douglas"));
System.out.println( "Hello World!" );
System.out.println(michaelDouglas.getId());
System.out.println("Total people: " + actors.count());
}
}
I have the configuration class setup as well:
package org.example.neo4jSpike;
import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableNeo4jRepositories(basePackages = "org.example.neo4jSpike.repositories")
#EnableTransactionManagement
public class SpikeConfiguration extends Neo4jConfiguration{
#Bean
public SessionFactory getSessionFactory() {
// with domain entity base package(s)
return new SessionFactory("org.example.neo4jSpike.domain");
}
// needed for session in view in web-applications
#Bean
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Session getSession() throws Exception {
return super.getSession();
}
}
I'll add the code for my repositories and domain classes if needed, but they're all set up in a similar manner, and are all pretty simple.
When I try and run the main, however, I get
No qualifying bean of type [org.example.neo4jSpike.App] is defined
I don't see how it's not defined, it's right there, defined as an #Component. What am I misunderstanding?
Doesn't matter if you put the #Component annotation if Spring is not scanning your class package. You can add a #ComponentScan annotation in you configuration class and configure it to scan the package where your App class is located. Alternatively you can remove the #Component annotation and declare a Bean of type App in the configuration class.
Hope this can help.