ClassCastException与CDI生产者方法和来自脚本的groovy类

ClassCastException与CDI生产者方法和来自脚本的groovy类,groovy,jboss-weld,weld,Groovy,Jboss Weld,Weld,我正在学习Groovy语言以及将其与CDI集成的可能性 在java类路径中,有一个名为Product的接口。我创建了一个CDI生产者方法,该方法返回产品类型。 在另一个类中,我执行来自CDI生产者方法的产品的注入 在类路径之外,我用一个简单的groovy类编写了一个groovy脚本,用于实现产品接口 在CDI生产者方法中,我使用GroovyScriptEngine从脚本中检索类对象,以创建CDIBean 我正在使用 焊接版本2.2.8.1最终版作为CDI实施 Groovy版本2.3.9 Tom

我正在学习Groovy语言以及将其与CDI集成的可能性

在java类路径中,有一个名为
Product
的接口。我创建了一个CDI生产者方法,该方法返回
产品
类型。 在另一个类中,我执行来自CDI生产者方法的
产品的注入

在类路径之外,我用一个简单的groovy类编写了一个groovy脚本,用于实现产品接口

在CDI生产者方法中,我使用
GroovyScriptEngine
从脚本中检索类对象,以创建CDIBean

我正在使用

  • 焊接版本2.2.8.1最终版作为CDI实施
  • Groovy版本2.3.9
  • Tomcat服务器7
  • 同时使用JSF2.2.8
(认为问题只与CDI eh Groovy的Weld实现有关)

第一次一切都很好。可以在JSF页面中使用创建的bean,单击in按钮并在服务器端执行操作,然后在浏览器上刷新页面。groovy脚本类上所有声明的方法和字段都可以被访问并与JSF页面一起使用。CDI容器还执行对
@PostConstruct
的调用。CDI生产者方法可以多次调用,并且所有的工作都可以进行

如前所述,第一时间一切正常。但是当groovy脚本更改时,会抛出一个
ClassCastException

有人能帮我解决这个问题吗?这是焊接/沟槽问题,还是根本不可能

产品
界面:

package test;

/**
 *
 * @author Welyab
 */
@ProductMethodIntercetor
public interface Product {

    public void a();

    public void b();
}
package test

class ProductImplWithGroovy  implements test.Product {
  @javax.annotation.PostConstruct
  def void init(){ 
        println "call init()"
  }

  def void a(){
      println "call a()";
  }

  def void b(){
      println "call b()";
  }

  def void c(){
      println "call c()";
  }
}
实现
产品
接口的groovy脚本:

package test;

/**
 *
 * @author Welyab
 */
@ProductMethodIntercetor
public interface Product {

    public void a();

    public void b();
}
package test

class ProductImplWithGroovy  implements test.Product {
  @javax.annotation.PostConstruct
  def void init(){ 
        println "call init()"
  }

  def void a(){
      println "call a()";
  }

  def void b(){
      println "call b()";
  }

  def void c(){
      println "call c()";
  }
}
生产者类别/方法:

package test;

import groovy.util.GroovyScriptEngine;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.CDI;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.util.AnnotationLiteral;

/**
 *
 * @author Welyab
 */
public class ProductsTest {

    private static GroovyScriptEngine se;

    static {
        try {
            se = new GroovyScriptEngine(new URL[]{
                new File("c:/users/welyab/desktop").toURI().toURL()
            });
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Produces
    @ProductProducer
    public Product criarProduto() {
        BeanManager bm = CDI.current().getBeanManager();

        final Class klazz;
        try {
            klazz = se.loadScriptByName("script_test.groovy");
        }
        catch (Exception ex) {
            throw new RuntimeException(ex);
        }
        Class finalKlazz = klazz;

        AnnotatedType annotatedType = bm.createAnnotatedType(finalKlazz);
        InjectionTarget injectionTarget = bm.createInjectionTarget(annotatedType);

        Bean bean = new Bean() {

            @Override
            public Class getBeanClass() {
                return finalKlazz;
            }

            @Override
            public Set getInjectionPoints() {
                return injectionTarget.getInjectionPoints();
            }

            @Override
            public boolean isNullable() {
                return false;
            }

            @Override
            public Object create(CreationalContext creationalContext) {
                Object instance = injectionTarget.produce(creationalContext);
                injectionTarget.inject(instance, creationalContext);
                injectionTarget.postConstruct(instance);
                return instance;
            }

            @Override
            public void destroy(Object instance, CreationalContext creationalContext) {
                injectionTarget.preDestroy(instance);
                injectionTarget.dispose(instance);
                creationalContext.release();
            }

            @Override
            public Set<?> getTypes() {
                Set<Type> types = new HashSet<>();
                types.add(finalKlazz);
                types.add(Product.class);
                types.add(Object.class);
                return types;
            }

            @Override
            public Set getQualifiers() {
                Set<Annotation> qualifiers = new HashSet<Annotation>();
                qualifiers.add(new AnnotationLiteral<Default>() {
                });
                qualifiers.add(new AnnotationLiteral<Any>() {
                });
                return qualifiers;
            }

            @Override
            public Class getScope() {
                return ApplicationScoped.class;
            }

            @Override
            public String getName() {
                return "product";
            }

            @Override
            public Set getStereotypes() {
                return Collections.emptySet();
            }

            @Override
            public boolean isAlternative() {
                return false;
            }
        };

        CreationalContext ctx = bm.createCreationalContext(bean);
        Product produto = (Product) bm.getReference(bean, finalKlazz, ctx);
        return produto;
    }
}
使用bean的JSF页面的一个简单片段

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                template="/install/ayszu-template.xhtml"
                xmlns:p="http://primefaces.org/ui"
                xmlns:jsf="http://xmlns.jcp.org/jsf"
                xmlns:h="http://xmlns.jcp.org/jsf/html">
    <ui:define name="body">
        <form jsf:id="form" >
            <h:commandButton value="a" action="#{testBean.product.a}" />
            <h:commandButton value="b" action="#{testBean.product.b}" />
            <h:commandButton value="c" action="#{testBean.product.c}" />
        </form>
    </ui:define>
</ui:composition>

您是否也可以添加stacktrace/ExceptionAnk以便重播。我用stacktrace更新。我注意到,如果groovy类名更改,脚本重新加载就可以工作了。重新加载将生成一个新类。代理需要旧类并用于新实例,或者代理用于新类并用于旧实例。代码中似乎有东西在缓存代理。@WelyabPaula您是否需要使用GroovyScript引擎?Groovy的联合编译使这段代码成为simplerI第二个@blackdrag注释的方式。另外,我相信如果重新启动应用程序,
ClassCastException
不会发生,因为类加载器中不会有
productimpwithgroovy.class