Problems changing from Load Time Weaver to Compile Time Weaver in Spring - spring

I'm trying to change from load-time-weaving to compile-time-weaving with my Spring 2.5 app.
To do this, I did the following:
In my ant build file, I added
<path id="aspectPath">
<pathelement location="${lib.home}/spring-aspects.jar"/>
</path>
<taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
<classpath>
<pathelement location="${aspectj.home}/aspectjtools.jar"/>
</classpath>
</taskdef>
and replaced the reference to the javac compiler with the following
<iajc sourceroots="${src.home}"
destdir="${build.home}/WEB-INF/classes"
classpathRef="compile.classpath"
aspectPathRef="compile.classpath"
debug="${compile.debug}"
deprecation="${compile.deprecation}"
encoding="cp1252"
source="1.6"
target="1.6"
showWeaveInfo="${compile.debug}"/>
In applicationContext.xml I then replaced
<context:load-time-weaver/>
with
<context:spring-configured/>
Other configuration settings in my app context file, BTW, include
<tx:annotation-driven/>
<context:component-scan base-package="com.domain.somepackage"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
In the context.xml file, I removed the following from the loader tag
loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
When I run the build script, it compiles without errors.
I do get this warning however.
[iajc] warning at <Unknown>::0 Found #DeclareAnnotation while current release
does not support it (see 'org.aspectj.weaver.bcel.AtAjAttributes')
at the top, and this warning at the bottom:
[iajc] warning at C:\server-
lib\aspectjtools.jar!org\aspectj\ajdt\internal\compiler\
CompilerAdapter.class:121::0 advice defined in
org.aspectj.ajdt.internal.compiler.CompilerAdapter has not been
applied [Xlint:adviceDidNotMatch]
Most of the logging looks like:
[iajc] weaveinfo Join point 'method-execution(void com.kjconfigurator.upgra
de.Upgrade1_07HelperImp.addServiceParticipation(com.kjconfigurator.core.domain.U
ser, com.kjconfigurator.core.domain.ServiceAccount))' in Type 'com.kjconfigurato
r.upgrade.Upgrade1_07HelperImp' (Upgrade1_07HelperImp.java:196) advised by after
Returning advice from 'org.springframework.transaction.aspectj.AnnotationTransac
tionAspect' (spring-aspects.jar!AbstractTransactionAspect.class:77(from Abstract
TransactionAspect.aj))
I removed the tomcatspringweaver jar from the tomcat lib.
I am using aspectj1.7
When I start the app up, I get an error indicating that when a dao class is being injected into a service class there is an NPE at at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:104)
Caused by: org.springframework.beans.PropertyBatchUpdateException; nested
PropertyAccessExceptions (1) are: PropertyAccessException 1:
org.springframework.beans.MethodInvocationException: Property 'dao' threw exception;
nested exception is java.lang.NullPointerException
The Dao class extends an AbstractJpaDao class that looks like this:
public abstract class AbstractJpaDao<T> {
private static Logger log = Logger.getLogger(AbstractJpaDao.class.getName());
private EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this. entityManager = entityManager;
}
...
}
It's been such a long time since all this was initially set up, I don't remember how all the configurations work. Nor do I understand class loaders or AspectJ very well. But something is not happening correctly, perhaps the Entitymanager is not being injected for some reason.
Questions.
What might be causing this?
Is <context:spring-configured/> really needed?
The package referenced by <context:component-scan base-package="com.domain.somepackage"/> does not include the Dao class in question. When I do add another component-scan tag with the dao's package in it, nothing different happens. Is this necessary?

Do you have any schedule tasks defined somewhere - it sounds like the scheduled tasks are getting triggered before the Spring context is completely initialized.

I finally found a solution to this problem with the help of a Spring consultant.
There was an aspect that was being called before it was fully initialized resulting in an NPE in the aspect. (Eclipse incorrectly showed the NPE originating in the class that was being advised.) I disabled the aspect by removing the annotations because the aspect was not critical; however, a better fix would have been for me to instruct Spring to initialize that class ahead of the others, or use a point cut expression that was more narrow and which excluded setter methods.

Related

Spring ConflictingBeanDefinitionException

I have ProjectA defining a MyService class.
ProjectA contains multiple concrete services, for example: SomeService.
Now I have ProjectB, which is a spring boot project, having ProjectA as dependency.
ProjectB may add some functions to SomeService by defining its own public class SomeService extends project.a.SomeService {...}. The beans are scanned via #ImportResource("applicationContext.xml").
applicationContext.xml:
<beans ...>
<context:component-scan base-package="project">
<context:include-filter type="assignable"
expression="project.a.MyService" />
</context:component-scan>
</beans>
Main problem is: This leads to ConflictingBeanDefinitionException:
Annotation-specified bean name 'someService' for bean class
[project.a.SomeService] conflicts with existing,
non-compatible bean definition of same name and class [project.b.SomeService]
Although the exception is really clear, I have no idea how to solve it. After my research I'm relativley sure setAllowBeanDefinitionOverriding(true) should solve my problem. Maybe I just do it at the wrong time, but it never helped (also I think true is the default value).
My attempt:
I tried to avoid all scanning and register my beans by myself as well:
GenericApplicationContext ctx = (GenericApplicationContext) SpringApplication.run(ProjectBApplication.class, args);
ctx.getBeanFactory().registerSingleton("someService", new project.b.SomeService());
...
I can filter MyServices specifically this way but now I'm running in autowiring problems using SomeService in other (following!) beans.
Maybe I'm just registering the someService bean wrong?
I've already read about BeanPostProcessors, but I did not get how they could help me and where to use them correctly.
Keep in mind: any solution will fit, no matter if filtering MyService's in code, in xml, just tell spring to overwrite beans with more specific ones or what ever.
I figured out I just registered the bean wrong. Using
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(service);
context.registerBeanDefinition(beanName, beanDefinition);
solved the autowireing problem and at the moment every thing works fine.

Injected bean reset to NULL in the Aspect

I am new Spring AOP and Aspectj. I have seen various posts related to injected bean in an aspect being null and I have run into a similar problem. I am still not clear how I should proceed to get past the problem I am currently encountering.
Issue: Currently we are using Spring 3.2.3 and all injection is through Annotation. In my case, the dependent bean is injected properly by Spring but at the point of execution the injected bean is NULL. BTW, this doesn't happen all the time but what I can say is the stack trace when it fails and when it succeeds is slightly different. When the injected bean is not null (I can successfully use the injected bean service), the call to the before advice (in the aspect) always happens before the target method is called as it should.When the injected bean is NULL, the call to the aspect is from the first statement of the target method. At this point, I think another aspect is instantiated and has no reference to the injected bean. Here is the aspect I have created:
#Component
#Aspect
public class Enable{
private NameService nameService;
#Autowired
public void SetNameService(NameSerice service){
// service is injected properly
this.nameSerice = service;
}
#Before("* *.*(..)")
public void callBefore(JoinPoint jp){
//sometimes nameService is null and sometimes it not not
this.nameService.lookup(...);
}
}
Examining the various posts, one way to get around this (as suggested in the post) is to configure the aspect in the XML configuration file and use the factory-method ="aspectOf" and in the configuration inject the reference to the NameService bean as a property. Our whole project uses Annotation based injection (as stated earlier). Assuming I can still configure the above aspect in an XML configuration file, how can I get the reference NameService bean Id so that I can add it to the configuration. I also saw a post related to using Configurable annotation but I assume that is for objects created outside the Spring IOC.
Currently, the aspects are woven using Aspectj compile option in pom.xml. Our root-context.xml contains the entry context:annotation-config and the aspect is injected into Spring IOC because component-scan is turned on for the folder where the aspect resides. Any help will be appreciated
This is well common error when use aspects in spring, you should add
<context:spring-configured/>
and
<aop:aspectj-autoproxy />
also add
#Configurable
#Aspect
public class Enable
To your appContext.xml
aspectOf is another style to do the above but I prefer use the nature of context.
It might be too late to answer this question. But i have come across the same situation and i fixed it as below.
1) Have a setter and getter for "NameService" in your aspect class.
2) Mark "NameService" with #Component ("nameService")
3) Configure "nameService" in xml configuration using setter injection.
4) Re-Start your server after making changes.
This should resolve the problem of getting null for "NameService" in aspect.

#Autowired in bean not in spring context

I am new to springs. Is there an alternative for autowired to be used in a ordinary java bean which is not present in spring context.
You can do so by using Spring #Configurable with some AspectJ magic.
If you need a detailed explanation, here is the link.
And here is a brief overview of how it can be achieved.
First you have some bean that you want injected somewhere:
#Component
public class InjectedClass {
// ...
}
Then, you have a class that is not spring-container managed, that you want to instantiate. You want autowiring to work with this class. You mark it as a #Configurable.
#Configurable
public class NonContainerManagedClass {
#Autowired
private InjectedClass injected;
// ...
}
Now you need to tell spring that you want this non-container managed autowiring to work. So you put the following in your spring configuration.
<context:load-time-weaver />
<context:spring-configured />
Now, since this kind of thing requires modification of the bytecodes of your #Configurable class. So you tell Tomcat to use a different classloader. You can do so by creating a context.xml in your application's META-INF diretory and putting the following in there.
<Context path="/youWebAppName">
<Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
useSystemClassLoaderAsParent="false"/>
</Context>
Now, Tomcat needs to find that classloader. You can ensure that by putting Spring's spring-tomcat-weaver.jar (probably named org.springframework.instrument.tomcat-<version>.jar) in your tomcat installation's lib directory, and voila, the aspectj magic starts working. For classes that are annotated with #Configurable annotation, the #Autowired dependencies are resolved automatically; even if the instances are created outside of the spring-container.
This is probably the only way to make that work with Spring, in a clean manner. Make sure that you have appropriate dependencies in your classpath.
Another way would be to use the full AspectJ functionality and providing custom aspects around all your constructors and handling the dependency-injection yourself.

SpringAOP, load-time-weaver, strange behavior

in this moment i am facing one problem and really dont know what i am doing wrong. I am coding logging for my webservice using Spring framework and AOP in #AspectJ style. I got two bundles - background and frontend. In background bundle I have LogAspect, which look like this:
#Aspect
public class LogAspect {
#Pointcut("#annotation(logMethod)")
public void logMethodAnnotated(LogMethod logMethod){}
#Before("logMethodAnnotated(logMethod)")
public void beforeLogMethodAnnotated(JoinPoint jp){
//actions
}
#After("logMethodAnnotated(logMethod)")
public void afterLogMethodAnnotated(JoinPoint jp){
//actions
}
}
and META-INF/spring/background-osgi.xml:
<context:annotation-config />
<context:component-scan base-package="simon.background"/>
<context:load-time-weaver />
and also META-INF/aop.xml:
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in our application-specific packages -->
<include within="simon.background.*"/>
<include within="simon.frontend.controller.*"/>
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="simon.background.log.LogAspect"/>
</aspects>
</aspectj>
In frontend bundle I've just put into aplicationContext.xml <context:load-time-weaver aspectj-weaving="on" />. But the code is acting very strange. I found out, that there is some problem, when I put into my advice methods JoinPoint as argument. (I mean, when I got advice methods without arguments, so there were no JoinPoin in method header, everything has been working fine and advices has been running before and after #LogMethod (my annotation, which I use to say, that i want to log this method) annotated methods). But now it is working like this:
- when I start server and so that the bundles are deployed for the first time, then the advices are run just for methods, they are #LogMethod annotated and belongs to background bundle, but not for annotated methods in frontend.controller.
- and in addition, when I have done some changes in one of my controllers, saved it and deployed just frontend bundle, then when I run #LogMethod annotated method, I got this error:
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.LinkageError: loader constraint violation: when resolving method "simon.background.log.LogAspect.afterLogMethodAnnotated(Lorg/aspectj/lang/JoinPoint;)V" the class loader (instance of com/springsource/kernel/userregion/internal/equinox/KernelBundleClassLoader) of the current class, simon/frontend/controller/HuhController, and the class loader (instance of com/springsource/kernel/userregion/internal/equinox/KernelBundleClassLoader) for resolved class, simon/background/log/LogAspect, have different Class objects for the type /aspectj/lang/JoinPoint;)V used in the signature
Any ideas what is going on and how can i fix it, so my program will be able to run advices correctly?
One additional note, it could maybe help: When I run this in Debug mode with advices without JoinPoint argument, I realized, that both advices were running twice for one method.
On running twice, could it be because you are using both and
at the same time? Difference between <context:annotation-config> vs <context:component-scan>
Your pointcut has been triggered twice because your expression only constraints annotation type. When a method is called, call() and execution() are both match this expression so.
You can use #annotation(xxx) && execution(* *(..)) on your point cut to restrict the condition on execution only.

How to import Java-config class into XML-config so that both contexts have beans?

I have a project where I need to bootstrap #Configuration java-config classes into the XML configuration.
To do that, I'm reading that I also need to include the following bean definition (along with the bean definitions of the classes annotated with #Configuration).
<bean class="org.springframework.config.java.process.ConfigurationPostProcessor" />
But, I end up receiving the following error:
Caused by: java.lang.ClassNotFoundException: org.springframework.config.java.process.ConfigurationPostProcessor
I have to assume I'm missing a jar somewhere, but my various web searches hasn't resulted in an answer yet. Any help would be greatly appreciated. Thanks.
EDIT: Evidently, I was reading old documentation, which is no longer current. Let me back up. My project contains older XML-based configuration. The newer code is all using 'Java-config'. With that said, the contexts are apparently completely separate. I'd like to 'import' a java-config class into the XML configuration, so that both contexts have those particular beans. Does anyone know how I can do that?
This actually ended up being fairly simple. To get a Java-config bean definition into the xml-config, simply define the Java-config class as a bean within the XML-config. There are no extra jars necessary.
#Configuration
public class SomeJavaConfig {
#bean
... [bean definition]
}
inside the XML-config, you define this class as a bean.
<!-- needed to pick up the annotated java-config -->
<context:annotation-config />
<!-- Importing java-config class, which are annotated with #Configuration -->
<bean name="SomeJavaConfig" class="[fully qualified path].SomeJavaConfig" />
The XML-config, which may be part of a different context, now has all the bean definitions defined within the JavaConfig class.
UPDATED - to included Alan Franzoni's comment below in the answer.
Alternatively to annotation-config you can use component-scan. Then you do not have to include the Configuration Bean in XML:
<context:component-scan base-package="[fully qualified package path]" />
See Difference between <context:annotation-config> vs <context:component-scan> for more details.
Should be in:
spring-javaconfig-<version>.jar

Resources