I excluded part of my project for easier reproduce problem: GitHub repo.
When I compile it by Javac everything works as expected. I see logging in console when I open URLs /user/ and /user/2/:
Access: execution(List ru.krivochenko.demo.user.UserController.getAll())
Access: execution(User ru.krivochenko.demo.user.UserController.getOne(Integer))
But I wanna use AspectJ compiler. When I switch to it, error occurs:
java.lang.NoSuchMethodError: ru.krivochenko.demo.logging.LoggingAspect: method <init>()V not found
As I understood it happens because there is not no-args constructor in LoggingAspect. If I add it, I get another error, because logger is not injected:
java.lang.NullPointerException: null
at ru.krivochenko.demo.logging.LoggingAspect.beforeGettingUsers(LoggingAspect.java:28) ~[classes/:na]
So, how we can see, AspectJ ignores Autowired constructor with args.
In branch via-setter of my repo I implemented another solution. I removed #Component annotation of LoggingAspect and replaced constructor injection to setter injection. In DemoApplication.java I added #Bean configuration of LoggingAspect. It works fine, but in some situations it requires getting dependencies from application context. What is the best practice to resolve it?
Thanks for help.
Spring Aspects and compile time weaving don't automatically integrate. This is primary because aspectj and spring are fairly separate and I suspect Spring's recommended approach is not to use compile time weaving.
So thus by default Aspects are not spring magic and we need to add a little bit of plumbing to ensure they are.
In this regard, it is important to note that Aspects are not spring managed (they are managed by aspectj so we need to add something to ensure they are).
Thus the reason why you need a parameterless constructor on your aspect (so must use field injection).
Traditionally I have had to add the following piece of xml to my xml config files:
<bean id="securityAspect" class="com.<skip>.security.AuthorizationAspect"
factory-method="aspectOf" autowire="byType" />
So this works because the AspectJ compiler adds the static method aspectOf to the aspects and this method is available for acquiring the instance of the Aspect that aspectj creates (and uses).
This method is obviously not available in the source so we can't just add to our application class (DemoApplication):
#Bean
public LoggingAspect loggingAspect() {
return LoggingAspect.aspectOf();
}
Then what to do? My next option was to write some reflective code to call this method then having looked at this very helpful example that demonstrates exactly what you need - The Aspects class from AspectJ has a utilty method that does this work for us, so adding the following to our DemoApplication we have success:
#Bean
public LoggingAspect loggingAspect() {
return Aspects.aspectOf(LoggingAspect.class);
}
Btw, remove the #Component from the LoggingAspect as that will mean both Aspectj and Spring create an instance of the class...
Btw, I'd also suggest you add the following to your test class to demonstrate the problem in a test:
#Autowired
private UserController controller;
#Test
public void contextLoads() {
controller.getAll();
controller.getOne(1);
}
Btw, other suggestions to address this problem used #Configurable. I suspect this might work but you'll need to make sure you include the spring aspects java in your aspectj compile time config and I suspect it may still not work as I'm not sure the Spring context will be ready in time. i.e. if the Aspect is created before the spring context then #Configurable won't work as the beans to be injected will not yet be created.
Your approach to configure the aspect via setter injection looks valid to me. For more information about how to use AspectJ in combination with Spring check out the corresponding chapter in the Spring manual, specifically the description about how to configure AspectJ aspects by Spring IoC. It is mostly explained in the context of LTW, but it should work pretty much the same for CTW.
Related
I have a Spring 3 project which acts as a Rest API, and wanted to wire a spring bean I have into an unmanaged class for logging purposes.
After trying many different things, what worked was marking my unmanaged class with the annotation #Configurable.
Like:
#Configurable
public class ClassNotManagedBySpring {
#Autowired
#Qualifier("myBean")
private MyBean myBean;
}
#Service("myBean")
public class MyBean {
#Autowired
#Qualifier("someOtherBean")
private SomeOtherBean someOtherBean;
}
And then in my beans.xml:
<context:spring-configured/>
So now let's say that ClassNotManagedBySpring.java, is one of 6 classes that all do something similar, except 3 of them ARE managed by spring because they have the #Component annotation.
But all 6 of these classes need to #Autowire MyBean.java and only some need the #Configurable annotation.
To note, I was already previously using AspectJ in this app for multiple other purposes.
I want to know what is the risk in my spring application by all of a sudden wiring spring managed dependencies into un managed classes in this way?
Can there be performance issues? Risks of errors at runtime?
If this isn't the best way of wiring a spring managed bean into an unmanaged class, what is?
I've been using #Configurable for years without issues, it's a very easy solution if you need app instantiated beans configured by Spring. My use cases were all in the UI tier. I also used #Configurable(preConstruction = true) whenever I needed autowired values already in the constructor. Of course, if you make millions of #Configurable objects it might be a performance issue, otherwise I wouldn't worry too much about it. The only small aesthetic problem I had was Eclipse giving me some red underlines at class definitions extending #Configurable classes, complaining that the hierarchy of class SomeClass is inconsistent, but it compiled them nevertheless, no errors in the Problems view or at runtime whatsoever.
I'm working on a project that uses the Java (not xml) flavour of Spring configuration for wiring up dependencies. It also has profiling logic that should be weaved via AspectJ onto the desired methods (via annotations). The setup is working and I can see classes from my desired package being weaved and profiling information being logged out of them.
The problem is that weaving does not work for #Bean classes. I've enabled debug in aop.xml via:
<weaver options="-XnoInline -Xreweavable -verbose -debug -showWeaveInfo">
And I can see classes in my desired package being weaved, but not the beans in the configuration. If I instantiate the classes directly (not inject them) weaving works.
Unfortunately, I can't post real code here, but here's a dumbed down example:
#Configuration
#EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
public class MySpringConfig {
#Bean
AnnotatedClass1 annotatedClass1() {
return new AnnotatedClass1(new AnnotatedClass2());
}
}
AnnotatedClass1 and AnnotatedClass2 live in the same package and weaving works on the one instantiated directly and not the one returned by the bean.
I've searched through the Spring AOP docs but I can't seem to find anything related to this. There is some magic you need to do for auto-proxying and some limitations for SpringAOP but load time weaving should just work as far as I can tell - I've tried on private methods for example and it worked.
The problem was the return type - if I do:
#Bean
Object annotatedClass1() {
return new AnnotatedClass1(new AnnotatedClass2());
}
the weaving starts to work for the bean as well. My initial assumption was that it has something to do with Spring caching the bean and not using the weaved version, but this didn’t make sense because:
load time weaving is supposed to act at, well… class load time :). Then, it doesn’t matter what the method returns, the class should have the aspects.
I’ve actually checked the debug output for both Spring and AspectJ and no mention of my class so it must have been ignored somehow.
This is the first time I’ve used this stuff, so I might be misunderstanding things. If anyone can explain why the return type of the #Bean method has anything to do with weaving I’d be happy to accept your answer instead of this one.
I'm learning Spring and looking at using Spring Test for my web app (JQuery/CXF/Hibernate). I have been using annotations to wire up my beans and noticed that this sometimes got into the way of polymorphism. For example I have a GenericDAO extended by all DAOs. It is also a concrete class used by simple services, so when I wired it for one of those services, ALL other DAOs became candidates for runtime wiring (because of polymorphism). I could solve that by wiring explicitly by type: #Resource(type= GenericDaoImpl.class), but this goes against the best practice of coding to interfaces ..
Now I want to create unit tests using a MockGenericDaoImpl, and integration tests using GenericDaoImpl. How will I override the annotations? I'm guessing the best approach is to stick to XML-based wiring, so that I can have several versions of beans.xml, one for prod, one for unit tests, one for integration tests, and possibly split them into parallel sub-files, as needed. Isn't this approach more flexible than depending on annotations that either scan to guess the appropriate candidate, or constrain polymorphism?
Can someone give me broad directions on how to organize my test configuration setup? Thank you!
How about using #Configuration class? If you're not familiar with this method - you can declare a class that replaces the XML context file and looks something like this:
#Configuration
#ComponentScan({ "com.project.dao"})
public class TestConfiguration {
#Bean
public GenericDao getGenericDao() {
return new MockGenericDaoImpl();
}
}
In the #ComponentScan annotation just put the relevant packages to scan. This way you're very flexible with the beans you're creating and the way to create them. You can injects mock to the beans whatever way you'd like.
Also you can create several test configurations, each configuration for a different purpose. In order to load the context you need to put this annotation on your test class:
#ContextConfiguration(classes={TestConfiguration .class})
Using XML configuration files prevent you from depending on Spring dependencies. You can replace it with another DI framework(maybe Guice, but this is not realistic for big projects I know). Using XML configuration files enables you to code cleanly.
I hate XML but I hate existence of not-business-logic-specific things in my code more.
I see you know how to overcome the test issues using XML configuration files. I will try to show how to overcome duplication of implementations(one real one mock implementation) problems using annotations.
You can define your beans via annotations. You can select implementation using aliases:
project.dev.properties:
my.project.dao.xDao=xDaoJpaBean
project.test.properties:
my.project.dao.xDao=xDaoMockBean
<alias name="${my.project.dao.xDao}" alias="xDao"/>
#Autowired
#Qualifier("xDao")
protected XDao xDao;
So you can select your implementation just using your properties file. If you want to use Annotations purely you can do this as well:
#Autowired
#Qualifier("${my.project.dao.xDao}")
protected XDao xDao;
Your build environment will specify which properties file to load, in return your bean will be assigned.
I have a circular reference in one of my projects at work using spring, which I am unable to fix, and fails with the following error at startup:
'org.springframework.security.authenticationManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
I tried to recreate the same problem at a smaller level in a sample project (without all the details of my work project). I have however been unable to come up with a plausible scenario where spring fails with an error.
Here's what I have:
public class ClassA {
#Autowired
ClassB classB;
}
public class ClassB {
#Autowired
ClassC classC;
}
#Component
public class ClassC {
#Autowired
ClassA classA;
}
#Configuration
public class Config {
#Bean
public ClassA classA() {
return new ClassA();
}
#Bean
public ClassB classB() {
return new ClassB();
}
}
I have a similar scenario in my project, which fails, and I was expecting spring to complain in my sample project as well. But it works fine! Can someone give me a simple example of how to break spring with the circular reference error?
Edit: I fixed the issue using javax.inject.Provider. The only other difference in the 2 projects was the annotations used were javax.inject.Inject and javax.annotation.ManagedBean in place of #Autowired and #Component.
You could use #Lazy to indicate that the bean is lazily created, breaking the eager cycle of autowiring.
The idea is that some bean on the cycle could be instantiated as a proxy, and just at the moment it is really needed it will be initialized. This means, all beans are initialized except the one that is a proxy. Using it for the first time will trigger the configuration and as the other beans are already configured it will not be a problem.
From one Issue in Spring-Jira:
#Lazy annotation that can be used in conjunction with #Configuration
to indicate that all beans within that configuration class should be
lazily initialized. Of course, #Lazy may also be used in conjunction
with individual #Bean methods to indicate lazy initialization on a
one-by-one basis.
https://jira.springsource.org/browse/SJC-263
Meaning that annotating your bean as #Lazy would be enough. Or if you prefer just annotate the configuration class as #Lazy as follows:
#Configuration
#Lazy
public class Config {
#Bean
public ClassA classA() {
return new ClassA();
}
#Bean
public ClassB classB() {
return new ClassB();
}
}
If you implement an interface of your beans this will work quite well.
This is an old thread, so I guess you almost forgot about the issue, but I want to let you know about the mystery. I encountered the same problem, and mine didn't go away magically, so I had to resolve the problem. I'll solve your questions step by step.
1. Why you couldn't reproduce the circular reference exception?
Because Spring takes care of it. It creates beans and injects them as required.
2. Then why does your project produce the exception?
As #sperumal said, Spring may produce circular exception if you use constructor injection
According to the log, you use Spring Security in your project
In the Spring Security config, they do use constructor injection
Your beans which injects the authenticationManager had the circular reference
3. Then why has the exception gone away mystically?
The exception may or may not occur depends on the creation order of beans. I guess you made several *context.xml files or so, and load them with config something like below in web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:*-context.xml</param-value>
</context-param>
The xml files will be loaded by XmlWebApplicationContext class and the loading order of files are not guaranteed. It just loads files from the file system. The problem is here. There's no problem if the class loads the application context file first, because your beans are already created when they are used for the construction injection of Spring Security. But, if it loads the Spring Security context file first, the circular reference problem occurs, because Spring tries to use your beans in the constructor injection before they had been created.
4. How to solve the problem?
Force the loading order of the xml files. In my case, I loaded the security context xml file at the end of the application context file by using <import resource="">. The loading order can be changed depends on environments even with the same code, so I recommend setting the order to remove potential problems.
According to Spring documentation, it is possible to get Circular dependency issue or BeanCurrentlyInCreationException by using constructor injection.
The solution to fix the issue is to use setters instead of Constructor injection.
Reference http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html.
I have added some groovy files to an existing java + spring project.
The project was working (i.e. past the tests).
I added "#Transactional" to one of the groovy methods and the tests broke.
(In order to add #Transactional, I had to change the Annotation on the class from #Service to #Controller, otherwise the #Transactional was ignored - yuck).
I started getting exceptions
The exceptions varied #Autowired did not find anything - NoSuchBeanDefinitionException
adding #Qualifier("loadTransactions") gave me the same
#Resource gave BeanNotOfRequiredTypeException: Bean named 'loadTransactions' must be of type [net.idt.workflow.LoadTransactions], but was actually of type [$Proxy33]
(I find this a better error message then the #Autowired that I always use :-( )
I changed the type to "Object" and the #Resource injection worked (I am a bit annoyed with #Autowired - so I did not bother trying that with Object :-/ )
I then used the following groovy code: loadTransactions.metaClass.object.process();which I feel "stinks", but WORKS.
My question is: how do I get the nice code that I expected i.e.
loadTransactions.process();
I should not have to know that the #Transactional is using some proxy
Thanks for your help
Shalom Deitch