Ambiente

Durante la realizzazione di una piattaforma basata sul motore di regole per la generazione di un configuratore di prodotto ci siamo imbattuti in una problematica interessante.
Abbiamo deciso di utilizzare Guvnor per permettere al committente di gestire in autonomia le regole di business del proprio configuratore. 
Il sistema di runtime utilizzerà poi i package creati su Guvnor in un engine Drools dedicata.

Abbiamo quindi bisogno che esista un set di dati su cui applicare le regole (potrebbe essere ad esempio un elenco prodotti o un elenco di opzioni) che funzioni sia runtime che in fase di progettazione e test.

Primo approccio

Inizialmente abbiamo realizzato il caricamento di questi dati nell'area di memoria di Drools attraverso un set di regole generate da un file xls.
Questa impostazione purtroppo rende difficile la gestione degli aggiornamenti di questi set di dati. Ogni aggiornamento consistenza di fatti in:

  • esportazione dal gestionale dei dati
  • trasformazione in xls
  • caricamento in guvnor
  • pubblicazione delle modifiche
  • infine utilizzo dal runtime

Pur essendo una situazione buona per testare i modelli di regole in fase di sviluppo, non è sufficientemente flessibile per gestire la manutenzione in produzione del sistema.

Soluzione

La soluzione alla quale siamo giunti prevede la realizzazione di una libreria di funzioni java che possa essere richiamata da una regola Drools e che generi i fatti nella working memory.

creare una libreria in java

Nella creazione della libreria si evidenziano i limiti dell'ambiente in cui viene eseguito l'engine di drools. 

  • non possiamo istanziare la classe
  • non possiamo preconfigurarne il funzionamento
  • classe con metodi statici
  • configurazione della connessione a DB

La nostra classe effettuerà una semplice connessione al db, eseguirà una query sql e ritornerà il risultato sotto forma di un array di mappe.

public class SizerLib {
 static {
  try {
   Class.forName("com.mysql.jdbc.Driver");
  } catch (ClassNotFoundException e) {}
 }

 public static List<Map<String, String>> execQuery(String connUrl,String u, String p, String sql) throws SQLException {
  final List<Map<String, String>> ret = new ArrayList<>();
  final Connection connection = DriverManager.getConnection(connUrl, u, p);
  final Statement selectStmt = connection.createStatement();
  final ResultSet rs = selectStmt.executeQuery(sql);
  final ResultSetMetaData vMetaData = rs.getMetaData();
  while (rs.next()) {
   final Map<String, String> m = new HashMap<>();
   for (int ii = 1; ii <= vColumnCount; ii++) {
    final String vString = rs.getString(ii);
    final String vColumnName = vMetaData.getColumnName(ii);
    m.put(vColumnName, vString);
   }
   ret.add(m);
  }
  return ret;
 }
}

Importare la libreria in Guvnor

deve essere copiata dentro la WEB-INF lib di guvnor o nella lib di tomcat

La libreria viene rilasciata sotto forma di JAR file connettente le classi (una per il momento) che la compongono 

it.myti.DroolsUtils

Usare la libreria in una regola

Per utilizzare la librearia creiamo una regola tecnica (DRL) che ci permetta di scrivere liberamente il testo che compone la regola.

L'accesso alla libreria, una volta inserita nel classpath, avviene senza nessuna previa dichiarazione

when
  $t: java.util.Map() from it.myti.GuvnorLib.query("jdbc:mysql://localhost/dati", "myti", "***", "select * from nometabella")
then
  System.out.println($t.colonna1 + " " + $t.colonna2)

Usare la libreria nel runtime 

In fase di runtime, quando dalla nostra applicazione java inizializziamo l'engine di drools ottenendo le regole da Guvnor, abbiamo bisogno che la libreria sia presente nel classpath del runtime assieme alle librerie di drools .

Riassunto

  • Creare la libreria usando metodi statici
  • Creare un JAR della libreria
  • Installare il JAR nella WEB-INF/lib di guvnor
  • Utilizzare il metodo della libreria in una regola DRL
  • Installare il JAR anche nel classpath dei runtime che eseguiranno le regole