3

I'm really very new to Spring AOP. In my application, I had configured HiddenHttpMethodFilter that converts method parameters into HTTP methods and enables Spring to handle other HTTP methods like DELETE, PUT etc including GET and POST.

It is some times necessary to disable this functionality especially when handling multipart requests. In order to disable it at a specific request (regarding mulripart), I was using the following code.

package resolver;

import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartResolver;

/**
 * Disables the spring multipart resolver for specific client requests and
 * therefore keeps the request intact so that controllers can process it in
 * whatever way they wish. This behaviour is triggered by a particular GET
 * parameter in the client request so it is configurable.
 * @see MultipartResolver
 */
@Aspect
public final class MultipartResolverDisablingAspect
{
    /**
     * GET parameter which, if present in request, enables advice.
     */
    private static final String DISABLING_HTTP_REQUEST_PARAMETER_KEY = "_multipartResolverDisable";

    private static boolean disablingParameterExists(final HttpServletRequest request) 
    {
        Assert.notNull(request);
        return request.getParameter(DISABLING_HTTP_REQUEST_PARAMETER_KEY) != null;
    }

    /**
     * If above GET parameter exists in request then prompt the spring multipart
     * resolver to always tell spring that request is not of type multipart.
     * Spring then does not process the request any further.
     * @param pjp
     * @param request
     * @return
     * @throws Throwable
     */
    @Around("isMultipartOperation() && args(request)")
    public Object disableIsMultipartOperation(final ProceedingJoinPoint pjp, final HttpServletRequest request) throws Throwable 
    {

        Assert.notNull(pjp);
        Assert.notNull(request);

        if (disablingParameterExists(request)) 
        {
            return Boolean.FALSE;
        }

        return pjp.proceed();
    }

    /**
     * Applies to any implementation of {@linkplain MultipartResolver}
     */
    @SuppressWarnings("unused")
    @Pointcut("execution(public boolean " + "org.springframework.web.multipart.MultipartResolver." + "isMultipart(javax.servlet.http.HttpServletRequest))")
    private void isMultipartOperation() {}
}

and in the application-context.xml file, the following xml is required.

<aop:aspectj-autoproxy proxy-target-class="false" />
<bean class="resolver.MultipartResolverDisablingAspect" /> <!--Registers the above bean (class)-->

This code was taken from this article under the section - MULTIPART RESOLVER DISABLING ASPECT.

It is meant to disable multipart processing by HiddenHttpMethodFilter when a GET parameter multipartResolverDisable=1 is used as a query string as specified by the code above so that one can use commons fileupload as usual (when multipartResolverDisable=1 is supplied as a query string)


The actual question is still not in the picture. This approach was earlier working correctly in the following environment (with NetBeans 6.9.1).

  • Spring 3.2.0
  • Apache Tomcat 6.0.26.6 with the Servlet API 2.5.

Recently I have upgraded NetBeans 7.2.1 with Apache Tomcat 7.0.35 which has the Servlet API 3.0. The Spring version is the same as it was before - Spring 3.2.0.

With this updates, the approach as described above caused the following exception.

Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name
'org.springframework.transaction.config.internalTransactionAdvisor':
Cannot resolve reference to bean
'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0'
while setting bean property 'transactionAttributeSource'; nested
exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name
'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0':
Initialization of bean failed; nested exception is
**java.lang.IllegalArgumentException: error at ::0 can't find referenced
pointcut isMultipartOperation**

Where the isMultipartOperation() is the last method in the above class.

There might be a small change to the code but I know a very little about AOP and cannot figure out the cause of this exception in this nice-looking code.

What is the cause of this exception? Dose it have to do something with the Servlet API?

Tiny
  • 27,221
  • 105
  • 339
  • 599

1 Answers1

2

I think you should change your around advice to

@Around("isMultipartOperation(..) && args(request)")

your pointcut annotation to

@Pointcut("execution(* org.springframework.web.multipart.MultipartResolver.isMultipart(..)) && args(request)")

and the pointcut annotated method to

private void isMultipartOperation(HttpServletRequest request) {}

From memory, I had this issue where I was trying to wrap a pointcut with some advice, and the advice had a different number of arguments to the pointcut. In your code you appear to be using @Around to target a pointcut with args(request), but your pointcut method has no such parameter.

jc1001
  • 384
  • 2
  • 9
  • Hi, thanks for the reply. I have tried exactly as you mentioned but unfortunately it didn't make any difference. The exception as mentioned in the question is kept throwing. Looking simple but I'm not sure why it doesn't work with a higher version of Spring - 3.2.0 which earlier was the case of the version 3.0.2. – Tiny Jan 31 '13 at 14:40
  • Are you using Maven? If so it might be worth checking the **dependency:tree** to see if some relevant jar (ex. aspectj / aspectjweaver) version has changed or has changed from required to optional. Are you using ****? Perhaps turn logging to trace **log4j.logger.org.springframework.aop=TRACE** and have a look at startup to see what aop relevant changes are being applied to your class and how they differ from the log output when using 3.0.2. – jc1001 Feb 01 '13 at 10:11
  • I just noticed that in some working aop (Spring 3.1.2) I have, the pointcut is specified as `@Pointcut(value = "execution(* a.b..*.*(..)) && @annotation(myAnnotation)")` with the around advice as `@Around("cachedMethod(myAnnotation)") public Object processCacheLookup(ProceedingJoinPoint pjp, MyAnnotation myAnnotation) throws Throwable {` - might be worth a try - again, not sure why it's working in one Spring version and not the other. – jc1001 Feb 01 '13 at 10:20
  • My project is not using Maven and therefore, there are no Mavan dependencies. I have given a try with `@Pointcut(value="execution("* org.springframework.web.multipart.MultipartResolver." + "isMultipart(javax.servlet.http.HttpServletRequest))&& @annotation(request)")` and the around advice as `@Around("isMultipartOperation(request)")` but the exception didn't disappear. – Tiny Feb 01 '13 at 17:31
  • In my `spring-security.xml` file, this pointcut expression - `execution(* dao.*.*(..))` is working correctly like - ` `. – Tiny Feb 01 '13 at 17:35
  • At my Tomcat's console, these warnings appear - `log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader). log4j:WARN Please initialize the log4j system properly`. Might these warnings be the reason? These warnings were also appearing before the updates in the question but the problem in the question was working correctly and indeed I don't know how to resolve these warnings. – Tiny Feb 01 '13 at 17:40
  • My library versions are `aopalliance-1.0.jar` and `aspectjtools-1.5.4.jar` – Tiny Feb 01 '13 at 17:41
  • @Tiny I don't think the log errors are relevant though they may be preventing some relevant log output that would give a hint as to why the advice isn't working. I think the log4j warning above is because a log4j settings file isn't found on the classpath - if you address this and include an appender set to trace for package **log4j.logger.org.springframework.aop** it might give you something to go on. – jc1001 Feb 04 '13 at 11:17
  • After reading [this](http://stackoverflow.com/q/1266139/1391249) question, I have created a `log4j.properties` file and configured in the `web.xml` file as mentioned in the answers to that question and those warnings about `log4j` disappeared. – Tiny Feb 05 '13 at 07:15