热代码替换是否适用于Eclipse中的Groovy?

时间:2015-06-30 00:11:24

标签: eclipse debugging groovy

我想知道是否有人能够可靠地在Eclipse中使用Groovy hot replace。我找不到任何有用的信息,所以我不确定它是否只是为其他人工作?或者没有人使用Eclipse来进行Groovy开发?

我尝试使用最新的Eclipse(4.5 Mars)和最新的Groovy-Eclipse插件(来自http://dist.springsource.org/snapshot/GRECLIPSE/e4.5/的Groovy Eclipse 2.9.2),我仍然无法获得可靠的热替换。

一些简单的热替换方案可以正常工作。但是,只需要一点点复杂性就会导致奇怪的Groovy异常。我在不同的情况下得到不同的错误,但我能够在一个简单的junit中重现一个错误,所以我将演示一个带有一些简化域对象的错误。

HotSwapTests.groovy

class HotSwapTests {
    @Test
    public void testHotReplace() {
        DefaultTxView transactionGroup = new DefaultTxView();

        List<Default> defaults = [];

        Default d1 = new Default(ProducerAccountTransactionType.REPAID_AMOUNT, ParticipantAccountType.DEFAULT);
        Default d2 = new Default(ProducerAccountTransactionType.REPAID_AMOUNT, ParticipantAccountType.DEFAULT);

        d1.setCancelledDefault(d2);

        defaults << d1;

        transactionGroup.setDefaultTransactions(defaults);


        while (true) {
            Default result = transactionGroup.getRepaymentTransaction();
            println result
        } 
    }
}

DefaultTxView.groovy

public class DefaultTxView {

    def List<Default> defaultTransactions;

    public Default getRepaymentTransaction() { return getTransactionOfType(REPAID_AMOUNT); }

    public Default getTransactionOfType(ProducerAccountTransactionType type) {
        return defaultTransactions.find { it.getType() == type };
    }

Default.java

The contents of this domain object are not really important - it's a simple POJO.

现在,为了测试热交换,我在标记的行上放置一个断点:

while (true) {
    Default result = transactionGroup.getRepaymentTransaction(); <<< break
    println result
} 

然后我转到DefaultTxView.groovy并修改传递给find方法的闭包内的代码:

public Default getTransactionOfType(ProducerAccountTransactionType type) {
    return defaultTransactions.find { it.getType() == type && it.getCancelledDefault() == null};
}

保存文件时,我没有收到任何警告或错误消息,但如果我现在尝试跳过修改后的行,则会出现以下异常:

java.lang.ArrayIndexOutOfBoundsException: 2
    at ca.gc.agr.app.web.jsf.producer.DefaultTxView$_getTransactionOfType_closure1.doCall(DefaultTxView.groovy:15)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:278)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.BooleanReturningMethodInvoker.invoke(BooleanReturningMethodInvoker.java:48)
    at org.codehaus.groovy.runtime.callsite.BooleanClosureWrapper.call(BooleanClosureWrapper.java:50)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.find(DefaultGroovyMethods.java:3060)
    at org.codehaus.groovy.runtime.dgm$175.invoke(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271)
    at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at ca.gc.agr.app.web.jsf.producer.DefaultTxView.getTransactionOfType(DefaultTxView.groovy:15)
    at ca.gc.agr.app.web.jsf.producer.DefaultTxView$getTransactionOfType$1.callCurrent(Unknown Source)
    at ca.gc.agr.app.web.jsf.producer.DefaultTxView.getRepaymentTransaction(DefaultTxView.groovy:11)
    at ca.gc.agr.app.web.jsf.producer.DefaultTxView$getRepaymentTransaction$0.call(Unknown Source)
    at ca.gc.agr.app.web.jsf.temp.HotSwapTests.testHotReplace(HotSwapTests.groovy:29)

在TomCat中运行我的webapp时得到非常相似的结果,修改该行后也有相同的异常。重新启动junit,或者TomCat使新行正常工作,因此它绝对是一个热门替换问题。

那么我做错了什么?任何建议将不胜感激。

2 个答案:

答案 0 :(得分:1)

我过去使用eclipse插件在web开发环境with groovy successfully中使用了热部署。

IIRC,我使用了groovyReset.jar,DCEVM和jdk1.7。

groovyReset.jar应该在类路径中并设置为java agent。我使用了groovy-eclipse插件文件夹中的一个(如eclipse/plugins/org.codehaus.groovy_2.3.7.xx-201411061335-e44-RELEASE/extras/groovyReset.jar

  

-javaagent:/groovyReset.jar

无需重新部署即可立即看到新的闭包和方法。当然,在一个方法中也包含一个简单的LOC。有时我需要重新启动虚拟机,但仍然呼吸新鲜空气。

在你的情况下,我认为至少groovyReset.jar必须存在。它负责重置元类。如果您反编译一个groovy类,您可以使用java.lang.Method数组检查反射调用的方法调用。在热代码交换时,此阵列出现故障,需要重置。

答案 1 :(得分:0)

我已经在Eclipse中添加了Groovy插件,并为项目添加了groovy nature。正确的雄心勃勃的Java代码(泛型容器)突然出现奇怪的错误消息(错误和不合逻辑)

Groovy自然项目过度,在运行时使用Groovy的小片段编写脚本而不是更改java字符。 删除groovy功能不会阻止这些奇怪的消息。

我有机会,新电脑,新版Eclipse Mars,每年一次从头开始