2017-06-07 2 views
0

J'ai besoin d'un KieContainer injectable CDI, qui utilise le KieScanner pour mettre à jour les règles lorsqu'un nouveau paquet de règles est ajouté au dépôt maven. La méthode ci-dessous fonctionne bien, mais elle fuit la mémoire car un nouveau TimerService est créé par le KieScanner chaque fois que le KieContainer est injecté. Comment puis-je créer une méthode de production KieContainer en utilisant le KieScanner qui ne démarre pas un nouveau KieScanner pour chaque KieContainer injecté?Comment créer un producteur KieContainer en utilisant le KieScanner?

@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

Avez-vous essayé de garder une trace du KieScanner actuel et d'y appeler 'shutdown()' lorsque vous recréer le nouveau KieContainer? – laune

+0

N'a pas essayé cela, mais pensait à cette solution aussi. Il se sent cependant comme une solution de contournement, car vous démarrez et arrêtez toujours le scanner. À mon avis, un scanner singleton devrait juste être en arrière-plan, créé au démarrage et ne recréer que si pour une raison quelconque le haricot est détruit –

+0

Voulez-vous que j'écrive une réponse en disant que s'il n'y a qu'une seule façon de le faire, alors chemin n'est pas une solution de contournement ;-)? Si vous avez besoin d'un nouveau scanner pour chaque nouveau conteneur, alors c'est tout. Il y a peut-être une bonne raison de ne pas pouvoir échanger des conteneurs dans un scanner en cours d'exécution mais je ne sais pas. Vous pourriez demander cela sur la liste Drools. – laune

Répondre

0

Réponse courte: Utiliser des étendues sur les méthodes de production. Les méthodes du producteur peuvent spécifier la portée du haricot produit. Ceci est clairement indiqué dans cdi specification

Réponse longue:

  1. Si le KieContainer est un objet réutilisable et il est sans danger pour tous les haricots de partager une instance, s'il vous plaît ne considérez annoter votre méthode de producteur avec @ApplicationScoped. Veuillez noter qu'il existe une différence entre @Singleton et @ApplicationScoped. Veuillez également noter que je parle de la méthode du producteur, pas de la classe du haricot producteur. Si le KieContainer n'est pas réutilisable, mais que le KieScanner interne est, créez une autre méthode de producteur annotée avec @ApplicationScoped et injectez ce KieScanner dans la méthode KieContainer. Il sera réutilisé.

  2. Si aucun de ceux-ci ne peut être réutilisé, veuillez considérer l'annotation de votre classe de producteur actuelle avec @Dependent.