2017-06-07 18 views
0

我需要一个CDI可注入KieContainer,它使用KieScanner在新规则包添加到Maven存储库时更新规则。下面的方法工作正常,但是由于KieScanner在每次注入KieContainer时都会创建一个新的TimerService,因此会泄漏内存。如何使用KieScanner创建一个KieContainer生产者方法,该方法不会为每个注入的KieContainer启动一个新的KieScanner?如何使用KieScanner创建KieContainer生产者?

@Slf4j 
@Singleton 
public class KieContainerProducer { 

    private static final String PROPERTIES_FILENAME = "scanner.properties"; 

    @Produces 
    public static KieContainer produceContainer() { 
     try { 
      ClassLoader loader = Thread.currentThread().getContextClassLoader(); 
      Properties properties = new Properties(); 
      try (InputStream is = loader.getResourceAsStream(PROPERTIES_FILENAME)) { 
       properties.load(is); 
      } 
      KieServices ks = KieServices.get(); 
      ReleaseId releaseId = ks.newReleaseId(
        properties.getProperty("groupId"), 
        properties.getProperty("artifactId"), 
        properties.getProperty("version")); 
      KieContainer kContainer = ks.newKieContainer(releaseId); 
      KieScanner kScanner = ks.newKieScanner(kContainer); 
      kScanner.start(60000L); 
      return kContainer; 
     } catch (FileNotFoundException ex) { 
      log.error("Properties file scanner.properties not found."); 
      log.debug("FileNotFoundException: ", ex); 
     } catch (IOException ex) { 
      log.error("{} file not found.", PROPERTIES_FILENAME); 
      log.debug("IOException", ex); 
     } 
     throw new IllegalStateException("There was an error in the KieContainerProducer"); 
    } 

} 
+0

当您重新创建新的KieContainer时,您是否尝试过跟踪当前的KieScanner并调用'shutdown()'? – laune

+0

还没有尝试过,但也在考虑这个解决方案。不过感觉这是一种解决方法,因为您仍在不断启动和停止扫描仪。在我看来,一个单身扫描器应该只是在后台运行,在启动时创建,并且只有在出于某种原因才重新创建时,该bean才会被销毁。 –

+0

您是否希望我写一个答案,如果只有一种方法可以实现,那么这个方式不是解决方法;-)?如果你需要为每个新容器安装一个新的扫描仪,就是这样。无法在正在运行的扫描程序中交换容器可能有很好的理由,但我不知道。你可以在Drools名单上提问。 – laune

回答

0

简短的回答:对生产方法的使用范围。生产者方法可以指定生产的bean的范围。这在cdi specification

龙答案明确提出:

  1. 如果KieContainer是可重用的对象,它是安全的,所有的豆类共享一个实例,请不要考虑@ApplicationScoped注释你的生产方法。请注意0​​和@ApplicationScoped之间的区别。另请注意我正在谈论生产者方法,而不是生产者bean类。如果KieContainer不可重复使用,但内部KieScanner是,创建另一个生产者方法注释@ApplicationScoped并注入该KieScanner到KieContainer方法。它将被重用。

  2. 如果这些都不能重复使用,请考虑使用@Dependent注释您当前的生产者类别。