SpringBootApplication is unable to find bean under subpackage - java

I encountered this error while starting my SpringBootApplication.
Description:
Field XXX in com.helloworld.www.batch.SomeServiceImpl required a bean of type 'com.helloworld.www.batch.repository.SomeRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.helloworld.www.batch.repository.SomeRepository' in your configuration.
This is my project layout where I have my SpringBootApplication and the Repository. I have annotated my SpringBootApplication with "#SpringBootApplication", but it was not able to find "SomeRepository" bean class.
Do I have to annotate it with "EnableJpaRepositories" and indicate the repository packages before it can detect the "SomeRepository" bean class?
com.helloworld.www
+SpringBootApplicationName.java
com.helloworld.www.batch.repository
+SomeRepositoryName.java
Updates to the post, I have annotated my Repository with #Repository, and it only contains an interface without any implementation classes.
#Repository
public interface SomeRepository extends PagingAndSortingRepository<SomeModel, Integer> { }
Here's my main application class under package "com.helloworld.www"
#SpringBootApplication
public class SomeApplication {
public static void main(String[] args) {
SpringApplication.run(SomeApplication.class);
}
}

I think its not a "simple" injection problem here.
It looks like you're using spring data.
And the Repository that must be injected is actually an interface rather than concrete bean implementation.
Spring Data engine should be able to "find" your repository and create a real implementation in runtime (backed by Proxy mechanism). Then it puts this generated proxy onto an application context and only after that it can be injected into other beans.
In this case it looks like this "engine" that turns the repository into bean didn't work for some reason, and hence at the moment of instantiation of the service (SomeServiceImpl) There is no actual bean that represent (has been generated out of) repository.
Its hard to tell more, because you don't show any spring data related configurations and do not provide the code of that Repository...

Related

Beans created by ImportBeanDefinitionRegistrar during autoconfiguration are not eligible for all bean postprocessors

I have implemented ImportBeanDefinitionRegistrar to create bean definitions from external source. It has to be registrar since I do not know in advance how many bean definitions will be created.
When I use the registrar on my Application class like this:
#SpringBootApplication
#Import(GenesysRegistrar.class)
public class IntegrationServer {
...
}
everything works fine.
I wanted to make the import automatic for every application that uses the JAR that contains the registrar so I have created following class:
#Configuration
#Import(GenesysRegistrar.class)
public class GenesysAutoConfiguration {
/**/
}
and registered it in META-INF/spring.factories under key org.springframework.boot.autoconfigure.EnableAutoConfiguration.
Now auto-configuration works, but I get following messages in log:
Bean 'xxx' of type [XXX] is not eligible for getting processed by all BeanPostProcessors
What is the difference between importing the registry from aplication class and from autoconfiguration class? I have found that following post processors are created AFTER my beans:
methodValidationPostProcessor
persistenceExceptionTranslationPostProcessor
webServerFactoryCustomizerBeanPostProcessor
errorPageRegistrarBeanPostProcessor
I have tried to put #AutoConfigureOrder(Integer.MAX_VALUE) on my auto-configuration class, but it does not change anything.
Any ideas how can I fix the order so beans from definitions created by my registrar are processed after all post processors? Why Spring creates them before all post processors? Any why the issue does not happen when using #Import on application class?
Early initialized beans are dependencies injected to other bean factoy by constructor injection.
If the bean factory uses property injection instead of construcotr injection it does not happen.
Question is if constructor injection on factory bean is "bad practise" - have not found anything that prohibits it.
Created ticket to spring-boot (as it happens only during boot auto-configuraiton):
Issue #20219

Bean parameter could not be found when migrating spring boot

I'm migrating services from spring boot 1.5 to spring boot 2.1 and I'm getting an error during this process. I have the following class for configuring my spring beans:
#Configuration
public class CompanyTransactionConfiguration {
public CompanyTransactionConfiguration() {
}
#Bean
public TransactionTaskRunner transactionTaskRunner(PlatformTransactionManager transactionManager) {
return new TransactionTaskRunnerImpl(this.readWriteTransactionTemplate(transactionManager), this.readOnlyTransactionTemplate(transactionManager), this.newReadWriteTransactionTemplate(transactionManager));
}
}
And, of course, a test class to check that everything work as expected:
#RunWith(SpringRunner.class)
public class ReferrerActivityRepositoryIT extends AbstractDomainIT {
#Autowired
private ReferrerActivityRepository referrerActivityRepository;
#Autowired
private TransactionTaskRunner transactionTaskRunner;
...
}
The issue is that this test was working fine after I changed my dependencies to a newer spring boot version (2.1), but now I'm getting the following error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method transactionTaskRunner in com.company.core.server.config.CompanyTransactionConfiguration required a bean of type 'org.springframework.transaction.PlatformTransactionManager' that could not be found.
The following candidates were found but could not be injected:
- Bean method 'transactionManager' in 'DataSourceTransactionManagerAutoConfiguration.DataSourceTransactionManagerConfiguration' not loaded because #ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) did not find any beans
- Bean method 'kafkaTransactionManager' in 'KafkaAutoConfiguration' not loaded because #ConditionalOnProperty (spring.kafka.producer.transaction-id-prefix) did not find property 'spring.kafka.producer.transaction-id-prefix'
...
Action:
Consider revisiting the entries above or defining a bean of type 'org.springframework.transaction.PlatformTransactionManager' in your configuration.
I don't know what is going on, maybe I need to add another dependency because of changes in spring boot or change my application.properties file. The question is why is this happening? What should I change to get this working?
Thanks!
You didn't define PlatformTransactionManager bean. I assume you don't want to make it by yourself. You have to add spring.kafka.producer.transaction-id-prefix property to property file in order to use KafkaAutoConfiguration for PlatformTransactionManager.
Bean method 'kafkaTransactionManager' in 'KafkaAutoConfiguration' not loaded because #ConditionalOnProperty (spring.kafka.producer.transaction-id-prefix) did not find property spring.kafka.producer.transaction-id-prefix
By the way your's CompanyTransactionConfiguration constructor is redundant as long as it doesn't have parameters. If there's no constructor in class compiler will create default one without parameters.

The bean could not be injected as a 'Type' because it is a JDK dynamic proxy that implements: reactor.fn.Consumer

My Spring 4 application, which uses Reactor 2, fails to start with:
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'orderHandlerConsumer' could not be injected as a 'fm.data.repository.OrderHandlerConsumer' because it is a JDK dynamic proxy that implements:
reactor.fn.Consumer
Action:
Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on #EnableAsync and/or #EnableCaching.
The OrderHandlerConsumer is really simple:
#Service
#Order(Ordered.HIGHEST_PRECEDENCE)
public class OrderHandlerConsumer implements Consumer<Event<OrderEnvelope>> {
#Override
public void accept(Event<OrderEnvelope> event) {
event.getData().getLatch().countDown();
}
}
Any ideas what might be going awry?
In your application class file where you define it as Spring application, add underneath it.
#SpringBootApplication
#EnableCaching(proxyTargetClass = true)
While the accepted answer will solve this issue, I think it will be more appropriate for me to explain why appling proxyTargetClass = true will fix this.
First of all, Spring, as a framework, utilizes proxing in order to supply the bean with some extended functionality, such as declaritive transactions via #Transactional, or caching by the means of #Cacheable and e.t.c. There are, in general, 2 ways(*) Spring can create proxy on top of your bean:
Jdk dynamic proxing
CGLib proxing
Offical documentation on this, in case you are interested.
Spring can create jdk dynamic proxy of the bean (in case proxing is required for this bean of course) if original class of the bean implements at least one interface. So spring basically create another implementation of this interface at runtime with some additional logic on top of original class.
What is the problem: if the bean is proxied by the means of jdk dynamic proxing , then you cannot inject this bean via its original class. So something like this:
#SpringBootApplication
#EnableTransactionManagement(proxyTargetClass = false)
public class StackoverflowApplication {
#Autowired private SomeService service;
public static void main(String[] args) {
SpringApplication.run(StackoverflowApplication.class, args);
}
}
#Service
class SomeService implements SomeInterface {
#Override
#Transactional
public void handle() { }
}
interface SomeInterface {
void handle();
}
wont work. Why? Well, becuase #Transactional tells Spring that it needs to create proxy of SomeService at runtime, and within #EnableTransactionManagement I specifically asked Spring to make it by the means of jdk dynamic proxy - spring will succeed, since jdk dynamic proxy can be created, but the problem is at runtime there is not bean of type SomeService, there is only a bean of type SomeInterface (by the way, if you inject service here not by the class, but by the interface - it will work, I assume you understand the reason by reading explaination above).
Solution: by applying #EnableTransactionManagement(proxyTargetClass = true) (notice true value here) you force spring to create CGlib proxy (this rule is applicable only for beans that utilize declarative transaction management, i.e. via annotations). In case of CgLib proxing, Spring will try to extend the original class, and add additional functionality at runtime in the generated child class. And in this case injection by class will work - because the bean extends class SomeService, so
#Autowired
private SomeService someService;
will work perfectly fine. But, in general, if possible, inject bean by interface, not by class. In this case both Cglib and jdk dynamic proxy will work. So, be aware of proxing mechanisms spring can use. Hope it helped, have a nice day.
You can assign a bean name to your OrderHandlerConsumer class so that Autowire resolution will be easier, Moreover, Instead of Autowiring with the concrete class, try to auto-wire with the interface. So that you can change #Service annotation to,
#Service(value="orderHandlerConsumer")
and try to Autowire with the interface type,
#Autowire
reactor.fn.Consumer orderHandlerConsumer;
Please try autowiring as below
class Test{
#Autowired
private Consumer orderHandlerConsumer;
}
If the target object to be proxied implements at least one interface
then a JDK dynamic proxy will be used. All of the interfaces
implemented by the target type will be proxied. If the target object
does not implement any interfaces then a CGLIB proxy will be created.
https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch08s06.html
You can call it two ways.
1st way is without mentioning the proxy [with default proxy], you can Autowire it by the interface like below.
#Autowired
private Consumer orderHandlerConsumer;
Spring AOP will create an instance for OrderHandlerConsumer.
2nd way is, mention the proxy in the bean as ScopedProxyMode.TARGET_CLASS.
then you can Autowire an instance without the interface [based on the class].
#Service
#Order(Ordered.HIGHEST_PRECEDENCE)
#Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class OrderHandlerConsumer implements Consumer<Event<OrderEnvelope>> {
#Override
public void accept(Event<OrderEnvelope> event) {
event.getData().getLatch().countDown();
}
}
and Autowire by the class like below.
#Autowired
private OrderHandlerConsumer orderHandlerConsumer;

Java Spring JPA Repository

I'm a Spring noob and I'm struggling with it.
Basically before starting develop my Server with Spring in conjunction with JPA I tried to start a simple example just to get used to this framework.
I've already get succeded in make Spring working with some frameworks as Log4J, Swagger and others. Now I'm trying to work with JPA and there are some points i can find out the solution.
I saw some blogs on how to develop with it and from all thousands options i choose to create my Repository Interfece and extend Repository<T, ID>. You can see my code bellow:
package com.example.model;
#Entity
public class Person {
#Id
public Integer id;
public String name;
public Person(){}
}
package com.example.repository;
public interface PersonRepository extends Repository<Person, Integer> {
Collection<Person> findAll();
}
package com.example.controller;
#RestController
public class PersonController {
#Autowired
private PersonRepository repo;
#RequestMapping(value = "/persons", method = RequestMethod.GET)
public Collection<Person> getAll() {
return repo.findAll();
}
}
package com.example;
#SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
And I also have the application.properties file:
spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://localhost:5432/test_db
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.driver-class-name=org.postgresql.Driver
When I put the server running I get the following exception:
: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.repository.PersonRepository com.example.controllers.PersonController.repo; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.repository.PersonRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations:
: Closing JPA EntityManagerFactory for persistence unit 'default'
: Stopping service Tomcat
: Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.repository.PersonRepository com.example.controllers.PersonController.repo; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.repository.PersonRepository] 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)}
I created a Github Repository to share the code here.
Any clue about what am I doing wrong?
First thing here is why you need to implements the base interface Repository as doing so, you will not have usual CRUD operations. For such operations is better to implements CrudRepository. Since you implement CrudRepository no need to define a findAll() Method and many well known others you can find in doc mentioned.
Furthermore, when using #SpringBootApplication Spring boot use default values. If you see the #SpringBootApplication definition you will see that :
Many Spring Boot developers always have their main class annotated with #Configuration, #EnableAutoConfiguration and #ComponentScan. Since these annotations are so frequently used together (especially if you follow the best practices above), Spring Boot provides a convenient #SpringBootApplication alternative.
The #SpringBootApplication annotation is equivalent to using #Configuration, #EnableAutoConfiguration and #ComponentScan with their default attributes: [...]
That means when using default values for ComponentScan your packages sturctures shloud be as following :
com.example.model -> your entities
com.example.repositoriy -> your repositories
com.example.controller -> controllers
com.example -> MainApplication class
Here is an example for default project structure
The main Application Class should be in higher level package then the others. Unless you have to specify packages location with #ComponentScan.
As you are beginner with the framework. I suggest you to always see classes definitions in official documentation.
UPDATE :
Here is an example from one of my spring boot projects
Also see this spring guide for JPA
Just annotate your interface with #Repository. And if that doesnt work try adding #EnableJPARepositories to the main class.
Try adding the #Repository annotation to your PersonRepository, that could be the reason it doesn't find it.
You need to annotate your PersonRepository interface with #Respository, otherwise the spring context won't recognize it or create an implementation for it.

Annotations declared in Abstract Class not being loaded

I have a Dynamic Web Project created in Eclipse (Juno) using Spring/Maven/Weblogic. I also have an Abstract class into which I inject a property (on the setter) via a properties file. The annotation used is #Value(value="${some.property}").
For some strange reason, when I deploy this project via maven to weblogic, the property gets injected for the concrete class that etends this Abstract class. But when I deploy this project directly onto weblogic via the Server -> Add Deployment, it fails to inject the property. In fact it does inject properties for all other annotations on the concrete class but ignores any annotations for the abstract class.
So basically this has nothing to do with coding but seems like some kind of config problem. Has anyone encountered something similar. Thanks.
public abstract class MyAbstract {
#Value(value="${myproperty1}")
public void setMyValue(String myValue) {
log.debug("setMyValue({})", myValue);
this.myValue = myValue;
}
}
public class MyConcrete {
#Value(value="${myproperty2}")
public void setMyValue2(String myValue2) {
log.debug("setMyValue2({})", myValue2);
this.myValue2 = myValue2;
}
}
I found the issue. The thing is that this particular bean has #Scheduled annotation and hence does not qualify for Bean Post Processing. Since the properties via #Value are set during this phase, they are skipped. Instead I shifted the bean creation into my application context xml file and set the properties from there eg.
<bean id="myConcrete" class="some.package.MyConcrete"
p:value="${myproperty1}"
/>
Now the properties are getting injected during normal bean lifecycle i.e. after Instantiation but before Bean Post Processor.

Categories