I need use a bean inject with #Component #FeignClient(name = "xxx") when my spring boot application initializing, but it always throws exception like this:
20180706 10:18:40,043 WARN [main]
[org.springframework.context.annotation.AnnotationConfigApplicationContext]
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'feignContract' defined in org.springframework.cloud.netflix.feign.FeignClientsConfiguration: Unsatisfied dependency expressed through method 'feignContract' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'feignConversionService' defined in org.springframework.cloud.netflix.feign.FeignClientsConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.format.support.FormattingConversionService]: Factory method 'feignConversionService' threw exception; nested exception is java.lang.StackOverflowError
my feignClient code:
#Component
#FeignClient(name = "domain-account")
public interface IDomainService {
#RequestMapping(value = "/userInfos", method = RequestMethod.GET)
public String getUserInfos(#QueryMap Map<String, Object> condition);
}
ApplicationListenner code:
public class GlobalInit implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
System.out.println("======== GlobalInit ========");
IDomainService domainService = contextRefreshedEvent.getApplicationContext().getBean(IDomainService.class);
System.out.println("*********************" + domainService);
GlobalInitManager.getInstance().doInit();
}
}
It's not entirely clear for me what you try to do with the GlobalInit but the 'standard' way of designing your Feign client in Spring Boot would the following:
#SpringBootApplication
#EnableFeignClients
#EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
#EnableCaching
public class MyHelloWorldApplication {
public static void main(String[] args) {
SpringApplication.run(MyHelloWorldApplication.class, args);
}
}
#Component
public class HelloWorldServiceImpl implements HelloWorldService {
#Autowired
private IDomainService iDomainService ;
public void myMethod() {
String userinfo = iDomainService.getUserInfos(...);
}
}
Hopefully this helps.
All the best,
Wim
Related
I have #ConditionalOnProperty(value = jms.enabled) on interface that extends JpaRepository, how I can test bean creation?
I try
private final ApplicationContextRunner runner =
new ApplicationContextRunner().withConfiguration(UserConfigurations.of(SomeRepository.class));
#Test
public void shouldCreateBeanWhenJmsEnabled() {
runner.withPropertyValues("jms.enabled=true")
.run(context -> assertThat(context).hasBean("someRepository"));
}
but I get
java.lang.AssertionError:
Expecting:
<Unstarted application context org.springframework.boot.test.context.assertj.AssertableApplicationContext[startupFailure=org.springframework.beans.factory.BeanCreationException]>
to have bean named:
<"someRepository">:
but context failed to start:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someRepository': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.kek.repository.SomeRepository]: Specified class is an interface
I need to stream a Object List, but when i try it using JpaRepository and #Query, i receive this exception:
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'MainApplication': Unsatisfied dependency expressed through field 'service'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'MyServiceImpl': Unsatisfied dependency expressed through field 'myDAO'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MyDAO': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.stream.Stream com.my.package.dao.MyDAO.streamAll()!
MyDAO code:
#Repository
public interface MyDAO extends JpaRepository<MyEntity, Long> {
#QueryHints(value = #QueryHint(name = HINT_FETCH_SIZE, value = "" +
Integer.MIN_VALUE))
#Query(value = "SELECT m FROM MyEntity m")
Stream<MyEntity> streamAll();
...
}
Main code:
#SpringBootApplication
#ComponentScan("com.my.package.*")
#EntityScan("com.my.package.*")
#Configuration
#EnableAutoConfiguration
public class MainApplication implements CommandLineRunner {
#Autowired
MyServiceInterface service;
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
try {
service.createCsv();
} catch (RuntimeException e) {
System.out.println(e);
}
}
}
I have tried everything but nothing works, please help me!
Just remove
#Query(value = "SELECT m FROM MyEntity m")
and use findAll() method of JPARepository like below
Stream<MyEntity> findAll();
You won't be able to use Stream<MyEntity> findAll(); because JpaRepository already defined the method with a List return type, so you can rename your method like that Stream<MyEntity> getAll(); or use Ordering to rename the method like Stream<MyEntity> findAllByOrderByIdAsc();.
I have a problem with Spring bean DefaultConfigurationService initialization that is extended from abstract class. I am totally stuck.
Class hiearchy is as follows:
public interface ConfigurationService {
TaxPayer getTaxPayer();
}
This class is mentioned to be useful for services that need to be initialized:
public abstract class BaseInitializationAwareService {
private boolean initialized = false;
public abstract void initialize();
protected void checkInitialization() {
if (!initialized) {
initialize();
}
}
protected void setInitialized() {
this.initialized = true;
}
}
This class acts as base class for Configuration service.
public abstract class BaseConfigurationService extends BaseInitializationAwareService implements ConfigurationService {
}
And with this bean, that acts as a configuration service, is a problem:
public class DefaultConfigurationService extends BaseConfigurationService {
private TaxPayerService taxPayerService;
#Autowired
public void setTaxPayerService(TaxPayerService taxPayerService) {
Assert.notNull(taxPayerService);
this.taxPayerService = taxPayerService;
}
public void initialize() {
Optional<TaxPayer> dbtaxPayer = taxPayerService.getActiveTaxPayer();
if (!dbtaxPayer.isPresent()) {
throw new IllegalStateException("Tax payer setting not found!");
}
this.taxPayer = dbtaxPayer.get();
setInitialized();
}
// the rest omitted...
}
when I'm creating DefaultConfigurationService bean:
#Bean
public BaseConfigurationService configurationService() {
DefaultConfigurationService configurationService = new DefaultConfigurationService();
configurationService.initialize();
return configurationService;
}
then taxPayerService in DefaultConfigurationService is null - it seems that is not autowired.
Can it be connected to the fact that DefaultConfigurationService is extended from abstract class?
TaxPayer service bean:
#Bean
public TaxPayerService taxPayerService() {
DatabaseTaxPayerService taxPayer = new DatabaseTaxPayerService();
return taxPayer;
}
This bean is probably never initialized...
Thats is a exception:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'webSecurityConfig.ApiSecurity':
Unsatisfied dependency expressed through method
'setContentNegotationStrategy' parameter 0; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
'org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration':
Unsatisfied dependency expressed through method 'setConfigurers'
parameter 0; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'passwordRecoverController': Unsatisfied
dependency expressed through method 'setUserService' parameter 0;
nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'defaultUserService': Unsatisfied
dependency expressed through method 'setNotificationService' parameter
0; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'notificationService': Unsatisfied
dependency expressed through method 'setConfigurationService'
parameter 0; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'configurationService' defined in class path
resource [com.example.config/AppConfig.class]: Bean instantiation via
factory method failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [com.example.services.BaseConfigurationService]: Factory
method 'configurationService' threw exception; nested exception is
java.lang.NullPointerException
For example, bean that needs BaseConfigurationService:
public class EmailNotificationService extends BaseService implements NotificationService {
private BaseConfigurationService configurationService;
#Autowired
public void setConfigurationService(BaseConfigurationService configurationService) {
Assert.notNull(configurationService);
this.configurationService = configurationService;
}
// the rest omitted...
}
#update 1
Bean initialization example with internal dependencies to another beans:
#Bean
public TransactionDataService transactionDataService() {
return new DefaultTransactionDataService();
}
and DefaultTransactionDataService:
public class DefaultTransactionDataService implements TransactionDataService {
private PrivateKeyService privateKeyService;
#Autowired
public void setPrivateKeyService(PrivateKeyService privateKeyService) {
Assert.notNull(privateKeyService);
this.privateKeyService = privateKeyService;
}
}
and bean dependency
#Bean
public PrivateKeyService privateKeyService() {
return new DefaultPrivateKeyAwareService();
}
and it works.
It is related to your instruction to Spring how to initialize your bean:
#Bean is used to explicitly declare a single bean, rather than letting Spring do it automatically as above. It decouples the declaration of the bean from the class definition, and lets you create and configure beans exactly how you choose.
So when you create instance of your class manually your have to set all class field manually as well.
It can be done like this:
#Bean
public BaseConfigurationService configurationService() {
DefaultConfigurationService configurationService = new DefaultConfigurationService();
configurationService.setTaxPayerService(taxPayerService());
configurationService.initialize();
return configurationService;
}
Or move dependency directly to constructor, so dependency of your DefaultConfigurationService will be more obvious:
#Bean
public BaseConfigurationService configurationService() {
DefaultConfigurationService configurationService = new DefaultConfigurationService(taxPayerService());
configurationService.initialize();
return configurationService;
}
Good description
I don't understand how spring boot's annotation #Autowired correctly works. Here is a simple example:
#SpringBootApplication
public class App {
#Autowired
public Starter starter;
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
public App() {
System.out.println("init App");
//starter.init();
}
}
--
#Repository
public class Starter {
public Starter() {System.out.println("init Starter");}
public void init() { System.out.println("call init"); }
}
When I execute this code, I get the logs init App and init Starter, so spring creates this objects. But when I call the init method from Starter in App, I get a NullPointerException. Is there more I need to do other than using the annotation #Autowired to init my object?
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'app': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [{package}.App$$EnhancerBySpringCGLIB$$87a7ccf]: Constructor threw exception; nested exception is java.lang.NullPointerException
When you call the init method from the constructor of class App, Spring has not yet autowired the dependencies into the App object. If you want to call this method after Spring has finished creating and autowiring the App object, then add a method with a #PostConstruct annotation to do this, for example:
#SpringBootApplication
public class App {
#Autowired
public Starter starter;
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
public App() {
System.out.println("constructor of App");
}
#PostConstruct
public void init() {
System.out.println("Calling starter.init");
starter.init();
}
}
Here is my class
#Configuration
class MongoDBConfig {
private Logger logger = LoggingFactory.getLogger(getClass());
#Bean
#Scope(value = "singleton", proxyMode = ScopedProxyMode.INTERFACES)
public MongoClient mongoClient() throws UnknownHostException {
logger.error("In Dev mode:");
return new MongoClient("fctest");
}
#Bean
public DB mongoDB() throws UnknownHostException{
try {
return mongoClient().getDB(FCProperties.MONGO_DB_NAME);
}catch (UnknownHostException ue){
logger.error("Error occurred: "+ue.getMessage());
throw ue;
}
}
}
And here is how I'm using it -
public class UserRepository extends BaseRepository {
#Autowired
public UserRepository(DB mongoDB) {
super("users", mongoDB);
}
}
I'm getting the following error
Error creating bean with name 'mongoDB' defined in class path resource [com/fctest/mongo/config/MongoDBConfig.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public com.mongodb.DB com.fctest.mongo.config.MongoDBConfig.mongoDB() throws java.net.UnknownHostException] threw exception; nested exception is java.lang.ClassCastException: com.sun.proxy.$Proxy13 cannot be cast to com.mongodb.MongoClient