In my some project I run into problem. Annotation #Transactional in some classes didn't work. After restarted module annotation is work. I open class in debug and saw that the CGLIB proxy is not used in the class, and used if I restart module without changes!
Eventually the problem was because project has custom library when in some class in #PostConstruct was registered beans duplicates of my beans with beanDefinitionRegistry.registerBeanDefinition() and after bean override in the part time class work without proxy. But I can't understand why? Why Spring create/ or replace/ or use bean without CGLIB proxy?
I was fixed that in my context, but I don't understand.
Related
I'm working on an integration with an older library so that it can use Spring Boot testing, and for that I need to register a certain bean very early in the process, so that an ApplicationListener<ApplicationReadyEvent> can add a PropertySource to the Environment.
This works fine in the normal startup, but when using the #SpringBootTest annotation I need to be able to inspect the TestContext very early and add it to the testing BootstrapContext, so that the application listener can access it also in the integration tests.
But I can't find a good way to add bean instances to the test BootstrapContext apart from specifying an initializer class in the spring.factories files, or am I missing something here?
I have been looking into using #BootstrapWith and subclassing SpringBootContextBootstrapper, but can't seem to find a way to add some kind of BootstrapregistryInitializer-like functions?
I have dependency in my spring boot project which fetches values of some properties using Spring's EnvironmentPostProcessor.
Now these properties are database credentials and not everyone has access to the credential since there is no dev environment for the db in question. I just want to change the configuration that the credentials don't get fetched on dev or local environment on application startup as that would result in a error and the application will fail to start.
Class A implements EnvironmentPostProcessor{}
I tried to use #Lazy annotation on the Class Annoteted with #ConfigurationProperties. I also tried using my own BeanFactoryPostProcessor (with #Order(HighestPrecedence) to programmatically set the A to lazy load, but it gets called before my BeanFactoryPostProcessor's postProcessBeanFactory method.
Is what I'm trying to achieve possible and am I going about it the wrong way?
#Lazy is only to be used with #Bean or #Component (Or any #Component-based annotations ex. #Service)
Take note: You can also add it to a #Configuration class, but that just means that all Beans in the class are annotated with #Lazy
#Lazy is a bit of a weird annotation in general; it should be seen as an IF possible then lazy load. If some other bean needs the lazy bean, the lazy bean will be initialized. (It's like the Pirate code, more of a guideline than an enforced rule)
Finally, marking #ConfigurationProperties with #Lazy seems a bit odd. As Spring will need these Configuration property "beans" to create the Spring Context.
However, the common use case for #Lazy is a failing database connection, preventing the application from starting. See the question if that is what you are running into.
Summary:
You can configure your repositories to be lazy-loaded with:
spring.data.jpa.repositories.bootstrap-mode=lazy
Last remark (Me just guessing)
If you wish to change properties once your application is already running, I would look at the following tutorial. It goes into manually reloading configuration and also #RefreshScope.
According to documentation EnvironmentPostProcessors must be registered via META-INF/spring.factories:
Allows for customization of the application's Environment prior to the
application context being refreshed. EnvironmentPostProcessor
implementations have to be registered in META-INF/spring.factories,
using the fully qualified name of this class as the key.
Implementations may implement the Ordered interface or use an #Order
annotation if they wish to be invoked in specific order.
I am trying to run a function in background asynchronously. For this I am trying Spring's #Async annotation but my application is unable to start after putting this annotation on the function.
I tried
#EnableAsync(proxyTargetClass = true)
but still no luck.
Below is the message I am getting on application start.
APPLICATION FAILED TO START
Description:
The bean 'MyBatchSyncProcessor' could not be injected as a 'com.a.b.c.service.MyBatchSyncProcessor' because it is a JDK dynamic proxy that implements:
com.a.b.c.service.BaseSyncProcessor
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.
Please help me out in getting this application up and running.
Don't inject your service implementation (MyBatchSyncProcessor) - inject its interface BaseSyncProcessor.
Although the first answer is correct, it doesn't really touches on why:
From https://www.fatalerrors.org/a/0dx20j8.html :
Async registers a Configuration configuration class with Spring using Spring's ImportSelector method, and injects a BeanPostProcessor, which calls the postProcessAfterInitialization method after the bean is instantiated to generate dynamic proxies for the object (if the target class implements an interface, the JDK proxy is used by default, otherwise CGLib is used)
When you combine this with :
(https://www.tutorialspoint.com/difference-between-jdk-dynamic-proxy-and-cglib-proxy-in-spring)
JDK dynamic proxy is available with the JDK. It can be only proxy by interface so target class needs to implement interface. In your is implementing one or more interface then spring will automatically use JDK dynamic proxies.
Now it becomes apparent that once you add the #EnableAsync aspect,
you need to inject the interface BaseSyncProcessor rather than its implementation MyBatchSyncProcessor, in beans that use the #Async annotation.
I am using autowiring in one of my projects. #autowiring is working fine in the controller, but I need to use same autowiring object in some other class, which is used as task class for quartz. Autowiring is not working there.
I tried this code listed below, but it did not succeed. In all attempts it's getting null for readXmlDao.
#Repository("updateTeam")
public class TeamUpdate {
#Autowired
#Qualifier("readXmlDao")
ReadXmlDao readXmlDao;
Please suggest a solution, thanks.
Autowire works in spring context (class instances managed by spring). Quartz creates its own contexts (creates its own instances). Spring do not have to know about these classes and its why autowires not working on them.
It is more spring/quartz configuration issue, than class annotation issue.
Spring will never leave an #Autowired target null. If it's processing the bean and can't find a match it will throw exceptions.
Since you are telling us it's null, the only possibility is that Spring is not managing your object. You're either creating a TeamUpdate object manually or some other process (not Spring) is creating it for you.
In your spring-servlet file make sure you are scanning the correct packages.
<context:component-scan base-package="your package here"/>
A lot of times you might have your controllers and your repositories in different packages. Make sure to scan both.
you might want to try this approach for using spring managed beans in a non-spring managed object.
http://www.javacodegeeks.com/2015/03/using-spring-managed-bean-in-non-managed-object.html
I have a 3-tier application: web-service, service-layer and domain-layer. The web service is present in a web application (WAR). The service-layer and domain-layer are two JAR projects. The dependencies are:
web-service --> service-layer --> domain-layer
In the service layer, the services are annotated with #Service. In the domain-layer, the DAOs are annotated with #Repository. The web service implementation class uses the services of the service-layer JAR, so it keeps one instance of each service which is automatically injected (#Autowired).
The dependencies are well defined in my POMs. When I deploy my WAR on Tomcat, I get the following exception:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.mycompany.project.services.MyService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:952)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:821)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:735)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:551)
... 37 more
I quote from one relevant part in the Spring docs:
The scanning of classpath packages requires the presence of
corresponding directory entries in the classpath. When you build JARs
with Ant, make sure that you do not activate the files-only switch of
the JAR task.
I've checked and the service-layer JAR is present in the WEB-INF/lib directory.
Any idea?
Thanks
EDIT: I have only one context file which is located in the web-service layer project (WAR) under src/main/webapp/WEB-INF. In this context, I've enabled classpath scanning as follows:
<context:component-scan base-package="com.mycompany.project" />
The package com.mycompany.project is the base package of my project, under which there are the web-service (com.mycompany.project.server), service-layer (com.mycompany.project.services) and domain-layer (com.mycompany.project.domain) packages.
I've solved the issue. I don't understand why what I've done was causing such an issue. Each service implements an interface that defines its public methods. In my web service implementation class, the references to the services used the implementation classes and not the interfaces. I just changed them to use the interface, and I don't get the issue anymore. Could anyone explain me what's wrong with using the services implementation classes instead of the interfaces for the autowiring?
This is an answer for your EDIT:
The reason why referring to the interface worked but the concrete implementation failed is probably to do with the dynamic proxies that Spring creates for cases where you have your services annotated with #Transactional etc. What happens in such cases is that the type of your beans are not the implementation type anymore, but wrap around your impementation type. So when you have #Autowired by implementation type, it just cannot find it by type (which is the default).
Your fix is very appropriate, as a dynamic proxy continues to derive from the interfaces that you have defined for your implementation and so can inject by interface type - the reference that I have provided does a better job explaining this.
make sure you used <context:component-scan base-package="your.service.package"/>
check your autowired strategy is byName or byType; if byName, the Service annotation's name value should be right.
if problem still exist, check spring's log, it will print all found components' name, you could know the service is founded or not.
Can you show your component scanning configuration? If this is not set up correctly then Spring may not be discovering your service.
You want something like:
<context:component-scan base-package="your.service.package"/>
Edit:
I think the problem is that your #Service annotation is on the interface rather than implementation class.
If you annotate your service implementation then your web controller can use either:
#Autowired
private ExampleService service;
or
#Autowired
private ExampleServiceImpl service;