Spring & AspectJ:Methode wird nicht aufgerufen

pizza1234

Erfahrenes Mitglied
Hallo,
ich hab gerade angefangen, mich mit AspectJ zu beschäftigen.
Ich möchte nun in meine SimpleFormControllern in Spring MVC ein Logging per Aspekt integrieren. Ich weiß nicht warum, aber irgendwie geht es nicht.

der Advice:
Java:
package de.etss.ccc.advices;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;

public class LoggingAdvice 
{

	private static final Logger logger = Logger.getLogger(LoggingAdvice.class);

	public void log(JoinPoint joinpoint)
	{
		logger.info("Test Logging");
		logger.info(joinpoint.getArgs());
		logger.info(joinpoint.getTarget());
		logger.info(joinpoint.getClass());

	}
}

die Konfiguration
Code:
	<bean id="loggingAdvice" 					class="de.etss.ccc.advices.LoggingAdvice">
	</bean>
	
	<aop:aspectj-autoproxy/>
	
	<aop:config>
		<aop:aspect ref="loggingAdvice">
		
		<aop:pointcut id="logging"
				expression="execution(* onSubmit*(..))"/>
				
		<aop:after-returning
				method="log"
				pointcut-ref="logging"/>	
		</aop:aspect>
	</aop:config>

Der Controller enthält folgende Methode, an die das Logging gehängt werden soll:
Java:
	@Override
	protected ModelAndView onSubmit(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException errors)
			throws Exception
{
return new ModelAndView("test");

}

Es gibt auch keine Fehlerausgabe und mit anderen Methoden zb. in den DAOs funktioniert es.

Grüße,
Peter
 
Hi Tom,

leider liegt es daran nicht! Ist es denn richtig, das durch das "autoproxy"-Element auch Proxys von Klassen erstellt werden, die keine Interfaces haben oder muss ich das irgendwo konfigurieren?
 
Um das zu erreichen musst du die Propery "proxy-target-class" oder so ähnlich auf true setzen und CGLib im Classpath haben.

Kann es desweiteren sein, dass das unqualifizierte onSubmit im Pointcut ein Problem ist? Ich würde erwarten, dass da wildcards für Package und Typ irgendwo auftauchen müssen.

Gruß
Ollie
 
Hallo,

ich tippe mal auch auf:
Um das zu erreichen musst du die Propery "proxy-target-class" oder so ähnlich auf true setzen und CGLib im Classpath haben.
Standardmäßig wird der (JDK) Dynamic Proxy based AOP Ansatz gefahren. Dabei werden nur Interface Methoden advised.
Wenn du nicht interface Methoden advisen willst muss du Spring mitteilen, dass es zur Laufzeit on-the-fly Subklassen (per CGLIb) von deinen Klassen erzeugen darf um AOP Logik einstreuen zu können.

XML:
...
<aop:config proxy-target-class="true">
		<aop:aspect ref="tracing">
...

Gruß Tom
 
Zuletzt bearbeitet von einem Moderator:
Hi, das ist ja alles sehr seltsam!
Ich habe jetzt cglib_nodep im classpath und proxy-target-class auf true, aber trotzdem wird der Pointcut nicht an die "onSubmit"-Methode gehängt. Selbst wenn ich einen vollqualifizierten Pfad einschließlich der onSubmit-Methode angebe, wird er nicht angehängt. Wenn ich meine Expression aber mal ändere, das alle Methoden (execution(public * *(..))) den Advice bekommen, sehe ich beim Debuggen zumindest den Proxy meines Controllers. An die onSubmit-Methode komme ich nicht ran!
 
Ich bin mir halt nicht sicher, dass protected Methoden überhaupt berücksichtigt werden. Hast du mal versucht, die public zu machen? Was du alternativ noch machen könntest, ist halt die handleRequest Methode aus dem Controller Interface zu intercepten. Die ist definitiv public und in einem Interface. Je nachdem, was du genu für Logging brauchst reicht es ja evtl. auch einfach das Loglevel für das mvc Package auf debug zu drehen?

Gruß
Ollie
 
Hi,
jetzt bin ich völlig verwirrt, auch den Controller kann ich nicht loggen!
Mache ich vielleicht was in der "expression" falsch?
Code:
		<aop:pointcut id="logging"
				expression="execution(* org.springframework.web.servlet.mvc.Controller.*(..))"/>
.
Oder kann es vielleicht sein, das es vielleicht an Spring Security liegt? Auf Service oder DAO-Ebene funktioniert ja alles.

Mit log4j zu loggen reicht nicht. Die Anforderung ist, sämtliche ausführenden Nutzeraktionen wie Speichern, Löschen, usw revisionssicher mitzuloggen. Ich dachte halt, am schnellsten gehts in der onSubmit-Methode, da ich dort ja (hoffentlich) an den Request und somit an den User komme. Dann muss ich jetzt wahrscheinlich auf die Service-Methoden ausweichen. Oder habt ihr noch eine Idee?

Grüße,
Peter
 
Hallo Kollegen,
ich arbeite mit Spring2.5.6 und den klassischen Controllern und bin jetzt genau auf das gleiche Problem wie pizza1234 gestoßen.
Auch bei mir wirkt bei alle Klassen im package der Pointcut - nur nicht in den von Spring MVC abgeleiteten Controller Klassen.
In diversen Foren wird dann beschrieben, dass man nur handleRequest vom AbstractController per Advice erreicht. Aber nicht mal folgendes funktioniert:

Code:
   <bean id="AspectBean"  class="mypackage.AspectClass" />
   <aop:config proxy-target-class="true">
        <aop:aspect id="myAspect" ref="AspectBean">
            <aop:pointcut id="test" expression="execution(* org.springframework.web.servlet.mvc.AbstractController.handleRequest(..))" />
            <aop:before pointcut-ref="test" method="test"/>
        </aop:aspect>
    </aop:config>

Gibt es mittlerweile eine Lösung?

Hier noch mein weiterer Code:
Code:
public class AspectClass{
private static Logger log = Logger.getLogger(AspectClass.class);
    public void test() { 
        log.info("Aspecttest: ");
    }
}

Welche Möglichkeiten habe ich per AOP an einen Controller ranzukommen?
Hilft eine Umstellung auf das neue Controller-Konzept (es ist schon spät im Projekt, aber vielleicht nicht zu spät und ich habe mich noch nicht damit beschäftigt).

beste Grüße - pasternak
 
Das ganze ist halt relativ logisch, wenn man es konsequent durchdenkt. Spring AOP basiert in der Standardkonfiguration auf einem proxybasierten Ansatz, der damit logischerweise erstmal nur mit Interfaces funktioniert. handleRequest(..) kommt allerdings aus dem Controllerinterface. D.h. es sollte in deinem Fall reichen einfach den Pointcut auf "...Controller+.handleRequest(..)" umzuschreiben.

Wenn du AOP für Klassen willst brauchst du CGLib im Classpath und musst die vVerwendung mit dem proxy-target-class="true" auf dem aop:config element aktivieren. Ich empfehle zum tieferen Verständnis das passende Kapitel aus der Spring Referenzdoku.

Für den von dir geschilderten Fall würde ich evtl sogar auf die AspectJ Annotationen umsteigen. So hättest du Pointcut und Advicemethode an einem Platz und sparst dir Konfiguration. Das aber nur als Hinweis. Hat nix mit dem Funktionieren an sich zu tun.

Gruß
Ollie
 
Zurück