开发者

NoSuchMethodException thrown by AnnotationValidationInterceptor when executing an action

Details of jars used: Struts2 2.2.1 Spring 3.0.5.RELEASE Hibernate 3.6.0.FINAL

I am experiencing a strange issue when trying to execute an action mapped as follows:

<action name="supplierSearch" class="supplierSearchAction">
            <result>/pages/suppliersearch.jsp</result>
</action>
<action name="searchForSupplier" class="supplierSearchAction" method="doSearch">
<result>/pages/suppliersearch.jsp</result>
</action>

the first action sends the user to a search page, they enter a search string and then the second action is invoked when the post the form.

The action in spring config is as follows:

<bean id="supplierSearchAction"
    class="com.blah.SupplierSearchAction"
    scope="prototype">
    <property name="searchService" ref="supplierSearchService"></property>
</bean>

the search service uses hibernate search and is defined as follows:

<bean id="supplierSearchService"
        class="com.devcentre.yubi.application.service.SupplierSearchServiceImpl">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>

I am using spring aop to configure my transaction boundaries and the persistence config is as follows:

<tx:annotation-driven transaction-manager="txManager" />

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="annotatedClasses">
            <list>
                // annotated classes here
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">upgrade</prop>
                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                <prop key="hibernate.cache.provider_class">
                    net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop>
                <prop key="hibernate.search.default.directory_provider">org.hibernate.search.store.FSDirectoryProvider
                </prop>
                <prop key="hibernate.search.default.indexBase">/lucene/indexes</prop>
                <prop key="hibernate.search.default.batch.merge_factor">10</prop>
                <prop key="hibernate.search.default.batch.max_buffered_docs">10</prop>
            </props>
        </property>

    </bean>

    <bean id="txManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

Spring is configured as follows in my web.xml:

<listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/src/spring-config.xml 
            /WEB-INF/src/persistence-config.xml 
        </param-value>
    </context-param>

On the search JSP page I have a form which submits the search string to the action which should invoke the doSearch method. However, when I submit the search I get an exception as follows (because devmode is enabled):

Struts has detected an unhandled exception:

Messages:    $Proxy28.doSearch()
File:   java/lang/Class.java Line
number: 1,605

and then the stack trace:

java.lang.NoSuchMethodException: $Proxy28.addComponent()
    java.lang.Class.getMethod(Class.java:1605)
    org.apache.struts2.interceptor.validation.Annotat开发者_如何学JAVAionValidationInterceptor.getActionMethod(AnnotationValidationInterceptor.java:75)
    org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:47)
    com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)

This is very odd because there is a method on the action class with the signature:

public String doSearch()

Can anyone help shed light on why the ActionProxy doesn't have the expected method?

Thanks,

Alex


java.lang.NoSuchMethodException: $Proxy25.doSearch()

Notice that the name of your action class is $Proxy25. It appears that something is creating a dynamic proxy to your action class. This is usually seen when using Aspect Oriented Programming (AOP) method interceptors on methods of a class — e.g., for things like transactions.

For example, I use Google Guice from time-to-time and when using AOP method interceptors on methods of a class, an action called LoginAction would have a dynamic proxy created called LoginAction$$EnhancerByGuice$$someAdditionalCharacters. While this dynamic proxy subclasses the methods of the class, it does not inherit annotations. My guess is that the same thing is happening here.

I don't use Spring, so I am not familiar with what libraries it uses to create dynamic proxies.

Update

If you remove the AOP annotations from your action class, then it should work as expected. Your action class can delegate to a service-layer class to handle persisting to the database (you can put the @Transactional annotation on that class's method(s)).


The struts2 spring & annotation integration seems to have its catches still...

the first call to getMethod from the AnnotationValidationInterceptor can be avoided using exclude parameters.

            <interceptor-ref name="validation">
                <param name="excludeMethods">YOURMETHODHERE</param>
            </interceptor-ref>

however, this simply postpones the problem until the actual method is called by the DefaultActionInvocation ending up at the same code location (getMethod Class#1597) which fails with the given method name on the proxy.

WORKAROUND

The only functional workaround I found was to use the standard execute() method for the action and split the actions up into different classes.

Hope that helps.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜