如何使 maven-failsafe-plugin 运行 Arquillian 功能测试知道堆栈跟踪中的 EJB 行号

How to make maven-failsafe-plugin running Arquillian functional tests aware of EJB line number in stacktrace

我正在 运行 使用 Arquillian 进行功能测试,它使用 Java EE 应用程序的完整 WAR,包括实体、EJB 接口和实现以及 webapp(JSF 页面和支持 bean) ) 安装到本地 Maven 存储库中,即测试非常接近集成测试。有时,我会遇到像

这样的堆栈跟踪
SomeRuntimeException
    [more container related calls]
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2060)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:90)
    at com.sun.proxy.$Proxy331.ejbMethod(Unknown Source)
    at package.JSFManagedBeanClass.method(JSFManagedBeanClass.java:[line number])

当 JSF backingb bean JSFManagedBeanClass 调用注入了 @EJB 的 EJB 的 ejbMethod 时,例如someEJB.ejbMethod.

我似乎不知道如何获取堆栈跟踪中 com.sun.proxy.$Proxy[number].ejbMethod(Unknown Source) 表示的 EJB 中发生异常的行号。

我尝试添加

<debug>true</debug>
<debugLevel>lines,vars,source</debugLevel>

maven-compiler-plugin 配置以及弄清楚 maven-war-plugin 中是否有一个选项 - 唯一似乎相关的是 warSourceIncludes,但这取决于 warSourceDirectory 如果仍然应该包含 webapp 内容,则无法更改。

添加

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <version>3.0.1</version>
    <executions>
        <execution>
            <id>attach-sources</id>
            <goals>
                <goal>jar</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <excludes>
            <exclude>target/generated-sources</exclude>
        </excludes>
    </configuration>
</plugin>

WAR POM 导致 maven-checkstyle-plugintarget/generated-sources 执行并在生成的 JPA 元模型上失败,这完全没有意义。

Arquillian @Deployment 方法:

@Deployment(testable = false)
public static Archive<?> createDeployment0() {
    WebArchive retValue = Maven.configureResolver().workOffline().resolve("[groupId]:[artifactId]:war:1.0-SNAPSHOT")
            .withoutTransitivity().asSingle(WebArchive.class);
    return retValue;
}

请注意,对于简单的 JAR 依赖项(与在故障安全插件测试运行程序中加载 Java EE WAR 相对),在线有很多修复,几乎所有修复都通过添加在其他上下文中提到了编译器配置选项或 -gjavac。现有的解决方案不涉及 com.sun.proxy.Proxy 这可能是特殊的。

当您调用 EJB 方法时,它总是通过代理。通常这个代理是在运行时生成的,它不会有行号,因为它没有源代码。

接下来会发生什么取决于实现,需要安排(至少):

  • 交易管理;
  • 安全;
  • 拦截器调用;
  • 异常管理(来自您的方法的 RuntimeExceptions 出现在 EJBExceptions 中)。

大约 你的实际方法调用。

如果您的 EJB 代码没有出现在堆栈跟踪中,则意味着在调用您的方法之前或之后出现了错误。

如果您展示了实际的堆栈跟踪(包括 "Caused by ..")和实际的异常,我们或许能够告诉您实际发生了什么。

我可以推测您正在调用有状态 EJB,而同一个 EJB 实例正处于另一个调用(来自较早的 HTTP 请求)的中间,因为我以前见过这种情况。有状态 EJB 强制执行 single-threaded 访问,因此您不会遇到同步问题。所以第二个调用是 chucking a wobbly(有时称为抛出异常)。