执行操作时 AnnotationValidationInterceptor 抛出 NoSuchMethodException

发布于 2024-11-04 13:41:43 字数 4418 浏览 2 评论 0原文

使用的罐子的详细信息: Struts2 2.2.1 春季 3.0.5.RELEASE Hibernate 3.6.0.FINAL

在尝试执行如下映射的操作时遇到一个奇怪的问题:

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

第一个操作将用户发送到搜索页面,他们输入搜索字符串,然后在发布表单时调用第二个操作。

spring配置中的操作如下:

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

搜索服务使用hibernate搜索,定义如下:

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

我使用spring aop来配置我的事务边界,持久化配置如下:

<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 在我的 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>

在搜索 JSP 页面上,我有一个表单,它将搜索字符串提交给应调用 doSearch 方法的操作。但是,当我提交搜索时,我收到如下异常(因为启用了 devmode):

Struts has detected an unhandled exception:

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

然后是堆栈跟踪:

java.lang.NoSuchMethodException: $Proxy28.addComponent()
    java.lang.Class.getMethod(Class.java:1605)
    org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.getActionMethod(AnnotationValidationInterceptor.java:75)
    org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:47)
    com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)

这很奇怪,因为操作类上有一个带有签名的方法:

public String doSearch()

任何人都可以帮助阐明原因ActionProxy 没有预期的方法?

谢谢,

亚历克斯

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.AnnotationValidationInterceptor.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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

森林很绿却致人迷途 2024-11-11 13:41:43

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

请注意,操作类的名称是 $Proxy25。似乎有东西正在为您的操作类创建动态代理。当对类的方法使用面向方面编程(AOP)方法拦截器时,通常会看到这种情况——例如,对于事务之类的事情。

例如,我时常使用 Google Guice,并且在类的方法上使用 AOP 方法拦截器时,名为 LoginAction 的操作将创建一个名为 LoginAction$$EnhancerByGuice 的动态代理$$someAdditionalCharacters虽然这个动态代理子类化了类的方法,但它不继承注释。我的猜测是这里发生了同样的事情。

我不使用Spring,所以我不熟悉它使用哪些库来创建动态代理。

更新

如果您从操作类中删除 AOP 注释,那么它应该按预期工作。您的操作类可以委托给服务层类来处理对数据库的持久化(您可以在该类的方法上放置 @Transactional 注释)。

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)).

御守 2024-11-11 13:41:43

struts2弹簧&注释集成似乎仍然有其缺陷...

可以使用排除参数来避免从 AnnotationValidationInterceptor 第一次调用 getMethod。

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

然而,这只是推迟了问题的发生,直到由 DefaultActionIn Vocation 调用实际方法并最终在同一代码位置 (getMethod Class#1597) 处结束,该方法因代理上的给定方法名称而失败。

解决方法

我发现的唯一有效的解决方法是对操作使用标准的execute() 方法并将操作分成不同的类。

希望有帮助。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文