Community
Participate
Working Groups
I am trying to profile JDBC access in a Spring-based application. Since all the JDBC interaction is performed through Spring classes, I need to weave into spring.jar. However, many of the classes referred by spring.jar aren't available to me (I am not using the functionality implemented by many of the classes). When I try to weave into spring.jar I get errors complaining that it can't find types for those classes. I expected that ajc would ignore unknown classes unless weaving would be affected by content/API of those classes. Using jar files that refer to foreign classes that one may never have/need is a common scenario. For example, spring.jar refers to Velocity, Struts, JDO, Hibernate, Quartz classes; I am unlikely to use all of these referred frameworks in an application. This bug/limitation prevents using AspectJ with such jars. To reproduce the bug in a controlled environment, I created the following aspect which should make the weaving process a pass-thru filter (no join point is matched by the pointcut) class TemporaryClass { } public aspect NoWeaveAspect { before() : call(* TemporaryClass.*(..)) && within(org.spring..*) { } } Weaving this aspect with spring.jar should result in logically identical jar file. However, when I compile using the following command (or equivalent ant task), I get the following errors: C:\work\aop\bugs\injar-with-nonexisting-classes>ajc -version AspectJ Compiler 1.2.1rc1 built on Friday Oct 22, 2004 at 13:31:47 GMT C:\work\aop\bugs\injar-with-nonexisting-classes>ajc -injars spring.jar -outjar s pring-woven.jar NoWeaveAspect.java C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.quartz.xml.JobSchedulingDataProcessor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.quartz.StatefulJob (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.quartz.SimpleTrigger (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe freemarker.cache.TemplateLoader (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.aopalliance.intercept.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.quartz.CronTrigger (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.aopalliance.intercept.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.quartz.JobDetail (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.quartz.Job (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.quartz.impl.jdbcjobstore.JobStoreCMT (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.apache.struts.action.PlugIn (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.apache.velocity.tools.generic.NumberTool (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.apache.struts.action.Action (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.apache.struts.tiles.TilesRequestProcessor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.apache.struts.action.RequestProcessor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.apache.velocity.runtime.resource.loader.ResourceLoader (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.apache.velocity.runtime.log.LogSystem (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe javax.faces.el.VariableResolver (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.apache.velocity.tools.generic.DateTool (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.apache.commons.attributes.AttributeRepositoryClass (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.aopalliance.intercept.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.aopalliance.intercept.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe net.sf.cglib.proxy.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.aopalliance.intercept.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.apache.commons.pool.PoolableObjectFactory (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.aopalliance.intercept.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe net.sf.cglib.proxy.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe net.sf.cglib.proxy.Dispatcher (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.aopalliance.intercept.MethodInvocation (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe net.sf.cglib.proxy.CallbackFilter (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe net.sf.cglib.proxy.NoOp (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe net.sf.hibernate.transaction.TransactionManagerLookup (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe net.sf.hibernate.connection.ConnectionProvider (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe net.sf.hibernate.UserType (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.apache.ojb.broker.accesslayer.ConnectionFactoryManagedImpl (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.aopalliance.intercept.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe net.sf.cglib.proxy.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe net.sf.cglib.proxy.CallbackFilter (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.aopalliance.intercept.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.aopalliance.intercept.MethodInterceptor (no source information available) C:\work\aop\bugs\injar-with-nonexisting-classes\spring.jar [error] can't find ty pe org.aopalliance.intercept.MethodInterceptor (no source information available) 41 errors
In order to fully identify some join points and determine if there is a match, ajc effectively needs the classpath when weaving that was used when the code was compiled. Without it, things like full hierarchy analysis can't be done. However, I take your point and have been thinking about what we can do. It is possible that in the case where we can't do full static analysis because you haven't supplied all the types, we might be able to simply insert more dynamic tests (of course, we'll tell you that we are doing it because you didn't supply all the types). In the short term, we could even at least tell you what we were trying to do when we couldn't resolve the type, so you could then decide whether to worry about it or simply ignore it.
this is a common problem. scheduling for investigation in m4.
the wished behavior (important for LTW as well) is: - type resolution must be as lazy as possible (f.e. getMethod called on a bcel class mirror should not trigger new type resolution, unless method params and returned values are actually queried etc, same with annotation, same with fields etc) Actually it is usually possible to have a string mirror for a method signature: void foo(bar.Baz) => method name = "foo", parameter[0] = mirror.getName = "bar.Baz", mirror.get() => trigger type resolution as a consequence of that: - if pointcut can be match without loading further types mirror, then it should not warn - if a pointcut does not further types mirror to do the match and those cannot be found, then its better to have a warning (and the pointcut expression / location) so that the user can narrow its pointcut (mainly: "+" in type patterns, method argument, method return value, annotation, field type, exception throwned)
I've made a big dent in this long-standing problem. The only message that the compiler produces now when compiling your example against spring.jar is XLint:adviceDidNotApply. I also tested with a similar example against struts.jar that weaved into the Action class (which refers to javax.servlet types not on the classpath). This now works too - though in that case the compiler puts out warning messages indicating that certain types could not be found and that this may have affected pointcut matching at the call / execution join point in question. The example in question is before() : execution(* Action.*(..)) when the supertypes of some struts types can't be found, we don't know for certain that those missing types don't themselves descend from Action (and hence might cause some methods in the type being analysed to match). But it's a likely bet that they don't, hence the warning rather than an error. For those interested in such things, the solution involves the following: * a new subtype of ResolvedType, MissingResolvedTypeWithKnownSignature. We create one of these when we can't resolve a type for which we know the signature. Instead of putting out the "can't find type" error straight away, we now only do so if a question is asked of the missing type that can't be answered solely based on signature. * In join point signature matching, switching to using a lazy iterator that only creates join point signatures when absolutely needed, rather than building all the signatures of a join point up front. * Every time we created a LazyClassGen, we looked to see if it implemented Serializable (so that lint warnings could be issued on operations affecting serializability). This requires chasing all supertypes of any given type looking for Serializable - which always caused a type not found if any parent type was not present. Now we tolerate a missing type in this situation and just assume that it did not implement Serializable - the only side effect is that some serializability warnings will not be issued that may have been had the type been present and it implemented Serializable and we performed some munging that affected it's serializability. * A similar parent-chasing scenario happens during preparation for weaving when we try to work out if a type exposed to the weaver and implementing an interface is the topmost implementor of that interface. This logic also now tolerates missing types, and assumes in this case that the sub-type in question is the topmost (it is certainly the topmost exposed to the weaver, which is all that matters here). * Finally, the can't find type messages themselves are much improved to give more information about why we were trying to find the type in the first place. Fix commited in tree and should be available for download in next published aspectj build.
Wonderful! Thank you very much.