/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jbpm.test.functional.monitoring;
import static org.junit.Assert.*;
import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.drools.core.ClockType;
import org.drools.core.management.DroolsManagementAgent;
import org.jbpm.process.instance.event.DefaultSignalManagerFactory;
import org.jbpm.process.instance.impl.DefaultProcessInstanceManagerFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.ReleaseId;
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.builder.model.KieSessionModel.KieSessionType;
import org.kie.api.command.BatchExecutionCommand;
import org.kie.api.command.Command;
import org.kie.api.conf.EventProcessingOption;
import org.kie.api.conf.MBeansOption;
import org.kie.api.management.GenericKieSessionMonitoringMXBean;
import org.kie.api.management.KieSessionMonitoringMXBean;
import org.kie.api.management.StatelessKieSessionMonitoringMXBean;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.KieSessionConfiguration;
import org.kie.api.runtime.StatelessKieSession;
import org.kie.api.runtime.conf.ClockTypeOption;
import org.kie.internal.command.CommandFactory;
import org.kie.internal.runtime.conf.ForceEagerActivationOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.management.JMX;
import javax.management.MBeanServer;
public class MBeansMonitoringWithJBpmTest {
public static final Logger LOG = LoggerFactory.getLogger(MBeansMonitoringWithJBpmTest.class);
public static final String KCONTAINER1 = "myContainerId";
public static final String KSESSION1 = "KSession1";
public static final String KBASE1 = "KBase1";
private static final String KSESSION2 = "KSession2_stateless";
private String mbeansprop;
@Before
public void setUp() throws Exception {
mbeansprop = System.getProperty( MBeansOption.PROPERTY_NAME );
System.setProperty( MBeansOption.PROPERTY_NAME, "enabled" );
}
@After
public void tearDown()
throws Exception {
if (mbeansprop != null) {
System.setProperty( MBeansOption.PROPERTY_NAME, mbeansprop );
} else {
System.setProperty( MBeansOption.PROPERTY_NAME, MBeansOption.DISABLED.toString() );
}
}
@Test
public void testRulesAndProcesses() throws Exception {
String drl = "package org.drools.droolsjbpm_integration_testmgt\n" +
"rule S\n" +
"when\n" +
" $s: String() \n" +
"then\n" +
" try { Thread.sleep(10); } catch (Exception e) { }\n" +
" System.out.println($s); \n" +
"end\n"
;
String process = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n" +
"<definitions id=\"Definition\"\n" +
" targetNamespace=\"http://www.example.org/MinimalExample\"\n" +
" typeLanguage=\"http://www.java.com/javaTypes\"\n" +
" expressionLanguage=\"http://www.mvel.org/2.0\"\n" +
" xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\"\n" +
" xmlns:xs=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xs:schemaLocation=\"http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd\"\n" +
" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\"\n" +
" xmlns:dc=\"http://www.omg.org/spec/DD/20100524/DC\"\n" +
" xmlns:di=\"http://www.omg.org/spec/DD/20100524/DI\"\n" +
" xmlns:tns=\"http://www.jboss.org/drools\">\n" +
"\n" +
" <process processType=\"Private\" isExecutable=\"true\" id=\"com.sample.HelloWorld\" name=\"Hello World\" >\n" +
"\n" +
" <!-- nodes -->\n" +
" <startEvent id=\"_a1\" name=\"StartProcess\" />\n" +
" <scriptTask id=\"_a2\" name=\"Hello\" >\n" +
" <script>System.out.println(\"Hello World\");</script>\n" +
" </scriptTask>\n" +
" <endEvent id=\"_a3\" name=\"EndProcess\" >\n" +
" <terminateEventDefinition/>\n" +
" </endEvent>\n" +
"\n" +
" <!-- connections -->\n" +
" <sequenceFlow id=\"_a1-_a2\" sourceRef=\"_a1\" targetRef=\"_a2\" />\n" +
" <sequenceFlow id=\"_a2-_a3\" sourceRef=\"_a2\" targetRef=\"_a3\" />\n" +
"\n" +
" </process>"+
" <process processType=\"Private\" isExecutable=\"true\" id=\"com.sample.CiaoWorld\" name=\"Ciao World\" >\n" +
"\n" +
" <!-- nodes -->\n" +
" <startEvent id=\"_b1\" name=\"StartProcess\" />\n" +
" <scriptTask id=\"_b2\" name=\"Ciao\" >\n" +
" <script>System.out.println(\"Ciao World\");</script>\n" +
" </scriptTask>\n" +
" <endEvent id=\"_b3\" name=\"EndProcess\" >\n" +
" <terminateEventDefinition/>\n" +
" </endEvent>\n" +
"\n" +
" <!-- connections -->\n" +
" <sequenceFlow id=\"_b1-_b2\" sourceRef=\"_b1\" targetRef=\"_b2\" />\n" +
" <sequenceFlow id=\"_b2-_b3\" sourceRef=\"_b2\" targetRef=\"_b3\" />\n" +
"\n" +
" </process>"+
"</definitions>";
KieServices ks = KieServices.Factory.get();
KieModuleModel kproj = ks.newKieModuleModel();
KieBaseModel kieBaseModel1 = kproj.newKieBaseModel( KBASE1 ).setDefault( true )
.setEventProcessingMode( EventProcessingOption.STREAM );
KieSessionModel ksessionModel1 = kieBaseModel1.newKieSessionModel( KSESSION1 ).setDefault( true )
.setType( KieSessionModel.KieSessionType.STATEFUL )
.setClockType( ClockTypeOption.get( ClockType.PSEUDO_CLOCK.getId() ) );
KieSessionModel ksessionModel2 = kieBaseModel1.newKieSessionModel( KSESSION2 ).setDefault( false )
.setType( KieSessionModel.KieSessionType.STATELESS );
ReleaseId releaseId1 = ks.newReleaseId( "org.kie.test", "mbeans", "1.0.0" );
KieFileSystem kfs = ks.newKieFileSystem();
kfs.writeKModuleXML(kproj.toXML());
kfs.generateAndWritePomXML(releaseId1);
kfs.write("src/main/resources/r" + 1 + ".drl", drl);
kfs.write("src/main/resources/p" + 1 + ".bpmn2", process);
KieBuilder kb = ks.newKieBuilder(kfs).buildAll();
if( kb.getResults().hasMessages( org.kie.api.builder.Message.Level.ERROR ) ) {
for( org.kie.api.builder.Message result : kb.getResults().getMessages() ) {
LOG.error(result.getText());
}
}
InternalKieModule kieModule = (InternalKieModule) ks.getRepository().getKieModule(releaseId1);
KieContainer kc = ks.newKieContainer( KCONTAINER1, releaseId1 );
KieBase kiebase = kc.getKieBase( KBASE1 );
Properties ksessionConfigProps = new Properties();
ksessionConfigProps.setProperty("drools.processSignalManagerFactory" , DefaultSignalManagerFactory.class.getName());
ksessionConfigProps.setProperty("drools.processInstanceManagerFactory" , DefaultProcessInstanceManagerFactory.class.getName());
KieSessionConfiguration sessionConf = ks.newKieSessionConfiguration(ksessionConfigProps);
sessionConf.setOption(ForceEagerActivationOption.YES);
KieSession ksession = kc.newKieSession(KSESSION1, sessionConf);
MBeanServer mbserver = ManagementFactory.getPlatformMBeanServer();
KieSessionMonitoringMXBean aggrMonitor = JMX.newMXBeanProxy(
mbserver,
DroolsManagementAgent.createObjectNameBy(KCONTAINER1, KBASE1, KieSessionType.STATEFUL, KSESSION1),
KieSessionMonitoringMXBean.class);
long tft = 0;
print(aggrMonitor);
checkAgendaTotals(aggrMonitor, 0, 0, 0);
checkTotalFactCount(aggrMonitor, 0);
tft = checkTotalFiringTimeGEQ(aggrMonitor, tft);
checkTotalSessions(aggrMonitor, 1);
assertNull( aggrMonitor.getStatsForProcess("com.sample.HelloWorld") );
assertNull( aggrMonitor.getStatsForProcess("com.sample.CiaoWorld") );
assertFalse( aggrMonitor.getStatsByProcess().containsKey("com.sample.HelloWorld") );
assertFalse( aggrMonitor.getStatsByProcess().containsKey("com.sample.CiaoWorld") );
ksession.insert("Ciao");
ksession.startProcess("com.sample.HelloWorld");
ksession.startProcess("com.sample.HelloWorld");
ksession.startProcess("com.sample.CiaoWorld");
ksession.fireAllRules();
print(aggrMonitor);
checkAgendaTotals(aggrMonitor, 1, 0, 1);
checkTotalFactCount(aggrMonitor, 1);
tft = checkTotalFiringTimeGEQ(aggrMonitor, tft + 1);
checkTotalSessions(aggrMonitor, 1);
checkStatsForProcess(aggrMonitor, "com.sample.HelloWorld" ,2,2,6);
checkStatsForProcess(aggrMonitor, "com.sample.CiaoWorld" ,1,1,3);
ksession.fireAllRules();
print(aggrMonitor);
checkAgendaTotals(aggrMonitor, 1, 0, 1);
checkTotalFactCount(aggrMonitor, 1);
tft = checkTotalFiringTimeGEQ(aggrMonitor, tft);
checkTotalSessions(aggrMonitor, 1);
checkStatsForProcess(aggrMonitor, "com.sample.HelloWorld" ,2,2,6);
checkStatsForProcess(aggrMonitor, "com.sample.CiaoWorld" ,1,1,3);
LOG.debug("---");
KieSession ksession2 = kc.newKieSession(KSESSION1, sessionConf);
ksession2.insert("Ciao");
ksession.startProcess("com.sample.HelloWorld");
ksession.startProcess("com.sample.HelloWorld");
ksession.startProcess("com.sample.CiaoWorld");
ksession2.fireAllRules();
print(aggrMonitor);
checkAgendaTotals(aggrMonitor, 2, 0, 2);
checkTotalFactCount(aggrMonitor, 2);
tft = checkTotalFiringTimeGEQ(aggrMonitor, tft + 1);
checkTotalSessions(aggrMonitor, 2);
checkStatsForProcess(aggrMonitor, "com.sample.HelloWorld" ,4,4,12);
checkStatsForProcess(aggrMonitor, "com.sample.CiaoWorld" ,2,2,6);
LOG.debug("--- NOW for the STATELESS ---");
tft = 0;
StatelessKieSession stateless = kc.newStatelessKieSession(KSESSION2, sessionConf);
StatelessKieSessionMonitoringMXBean aggrMonitor2 = JMX.newMXBeanProxy(
mbserver,
DroolsManagementAgent.createObjectNameBy(KCONTAINER1, KBASE1, KieSessionType.STATELESS, KSESSION2),
StatelessKieSessionMonitoringMXBean.class);
print(aggrMonitor2);
checkAgendaTotals(aggrMonitor2, 0, 0, 0);
checkRuleRuntimeTotals(aggrMonitor2, 0, 0);
tft = checkTotalFiringTimeGEQ(aggrMonitor2, tft);
checkTotalSessions(aggrMonitor2, 0);
List<Command> cmds = new ArrayList<Command>();
cmds.add(CommandFactory.newInsert("Ciao"));
cmds.add(CommandFactory.newStartProcess("com.sample.HelloWorld") );
cmds.add(CommandFactory.newStartProcess("com.sample.HelloWorld") );
cmds.add(CommandFactory.newStartProcess("com.sample.CiaoWorld") );
BatchExecutionCommand batch = CommandFactory.newBatchExecution(cmds);
stateless.execute(batch);
print(aggrMonitor2);
checkAgendaTotals(aggrMonitor2, 1, 0, 1);
checkRuleRuntimeTotals(aggrMonitor2, 1, 0);
tft = checkTotalFiringTimeGEQ(aggrMonitor2, tft + 1);
checkTotalSessions(aggrMonitor2, 1);
checkStatsForProcess(aggrMonitor2, "com.sample.HelloWorld" ,2,2,6);
checkStatsForProcess(aggrMonitor2, "com.sample.CiaoWorld" ,1,1,3);
stateless.execute(batch);
print(aggrMonitor2);
checkAgendaTotals(aggrMonitor2, 2, 0, 2);
checkRuleRuntimeTotals(aggrMonitor2, 2, 0);
tft = checkTotalFiringTimeGEQ(aggrMonitor2, tft + 1);
checkTotalSessions(aggrMonitor2, 2);
checkStatsForProcess(aggrMonitor2, "com.sample.HelloWorld" ,4,4,12);
checkStatsForProcess(aggrMonitor2, "com.sample.CiaoWorld" ,2,2,6);
StatelessKieSession stateless2 = kc.newStatelessKieSession(KSESSION2, sessionConf);
LOG.debug(stateless + " " + stateless2);
checkTotalSessions(aggrMonitor2, 2);
stateless2.execute(batch);
print(aggrMonitor2);
checkAgendaTotals(aggrMonitor2, 3, 0, 3);
checkRuleRuntimeTotals(aggrMonitor2, 3, 0);
tft = checkTotalFiringTimeGEQ(aggrMonitor2, tft + 1);
checkTotalSessions(aggrMonitor2, 3);
checkStatsForProcess(aggrMonitor2, "com.sample.HelloWorld" ,6,6,18);
checkStatsForProcess(aggrMonitor2, "com.sample.CiaoWorld" ,3,3,9);
}
private void checkStatsForProcess(GenericKieSessionMonitoringMXBean mb, String ruleName, long iStarted, long iCompleted, long nodesTriggered) {
assertEquals(iStarted , mb.getStatsForProcess(ruleName).getProcessInstancesStarted() );
assertEquals(iCompleted , mb.getStatsForProcess(ruleName).getProcessInstancesCompleted() );
assertEquals(nodesTriggered, mb.getStatsForProcess(ruleName).getProcessNodesTriggered() );
}
/**
* Utility method to add locally in test methods so to deliberately block on system.in, allowing time to use jvisualvm to inspecti the JMX manually.
*/
private static void blockOnSystemINforENTER() throws Exception {
Runnable task2 = new Runnable() {
@Override
public void run() { System.out.println("Press ENTER to continue: "); Scanner sin = new Scanner(System.in); sin.nextLine(); }
};
ExecutorService es = Executors.newCachedThreadPool();
es.submit(task2).get();
}
private void checkStatsByRule(GenericKieSessionMonitoringMXBean mb, String ruleName, long mCreated, long mCancelled, long mFired) {
assertEquals(mCreated , mb.getStatsByRule().get(ruleName).getMatchesCreated() );
assertEquals(mCancelled , mb.getStatsByRule().get(ruleName).getMatchesCancelled() );
assertEquals(mFired , mb.getStatsByRule().get(ruleName).getMatchesFired() );
}
private void checkStatsForRule(GenericKieSessionMonitoringMXBean mb, String ruleName, long mCreated, long mCancelled, long mFired) {
assertEquals(mCreated , mb.getStatsForRule(ruleName).getMatchesCreated() );
assertEquals(mCancelled , mb.getStatsForRule(ruleName).getMatchesCancelled() );
assertEquals(mFired , mb.getStatsForRule(ruleName).getMatchesFired() );
}
private void print(GenericKieSessionMonitoringMXBean mb) {
LOG.debug("total match created : {}",mb.getTotalMatchesCreated());
LOG.debug("total match cancelled: {}",mb.getTotalMatchesCancelled());
LOG.debug("total match fired : {}",mb.getTotalMatchesFired());
if (mb instanceof StatelessKieSessionMonitoringMXBean) {
StatelessKieSessionMonitoringMXBean c = (StatelessKieSessionMonitoringMXBean) mb;
LOG.debug("inserted and deleted : +{} -{}",c.getTotalObjectsInserted(),c.getTotalObjectsDeleted());
} else if (mb instanceof KieSessionMonitoringMXBean) {
KieSessionMonitoringMXBean c = (KieSessionMonitoringMXBean) mb;
LOG.debug("total tact count : {}",c.getTotalFactCount());
}
LOG.debug("{} ms .", mb.getTotalFiringTime());
}
private long checkTotalFiringTimeGEQ(GenericKieSessionMonitoringMXBean mb, long amount) {
assertTrue(mb.getTotalFiringTime() >= amount);
return mb.getTotalFiringTime();
}
private void checkTotalSessions(GenericKieSessionMonitoringMXBean mb, int totalSessions) {
assertEquals(totalSessions, mb.getTotalSessions() );
}
private void checkTotalFactCount(KieSessionMonitoringMXBean mb, int factCount) {
assertEquals(factCount , mb.getTotalFactCount() );
}
private void checkRuleRuntimeTotals(StatelessKieSessionMonitoringMXBean mb, int inserted, int deleted) {
assertEquals(inserted , mb.getTotalObjectsInserted() );
assertEquals(deleted , mb.getTotalObjectsDeleted() );
}
private void checkAgendaTotals(GenericKieSessionMonitoringMXBean mb, long mCreated, long mCancelled, long mFired) {
assertEquals(mCreated , mb.getTotalMatchesCreated() );
assertEquals(mCancelled , mb.getTotalMatchesCancelled() );
assertEquals(mFired , mb.getTotalMatchesFired() );
}
}