With Drools 6.x how do I avoid Maven and the Compiler? - maven

I'm looking into providing a 'hot-swap' capability for switching between different versions of sets of drools rules. The target deployment is in WebSphere, and the rules will all be run in stateless session beans. Ideally I want to pre-compile and package the rules into some discrete file and get the Application Server to determine that new rules are available, and load them (skipping the compilation step).
The Drools documentation indicates this should be possible - but is splendidly vague on the mechanics. The details on the Java EE side are not an issue but the pre-compilation is providing an headache.
Following some posts I've pulled together some logic which I thought would do the trick - the following compiles a rules file and serializes it out to disk:
private void process(String outputFile, String inputFile) throws Exception {
String drl = fileToString(inputFile);
KieServices ks = KieServices.Factory.get();
KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", drl );
ks.newKieBuilder( kfs ).buildAll();
ReleaseId releaseId = ks.getRepository().getDefaultReleaseId();
InternalKieModule kieModule = (InternalKieModule) ks.getRepository().getKieModule( releaseId );
byte[] jar = kieModule.getBytes();
serialize(jar, outputFile);
System.out.println("Class of InternalKieModule is " + kieModule.getClass());
}
The following reads it back ready to create a KieSession:
private KieContainer getKbase(KieServices ks) throws Exception {
byte[] jar = deserialize(RULES_SER);
Resource jarRes = ks.getResources().newByteArrayResource(jar);
KieModule km = ks.getRepository().addKieModule(jarRes);
releaseId = km.getReleaseId();
KieContainer kc = ks.newKieContainer(km.getReleaseId());
return kc;
}
Works fine BUT ... I was horrified to discover I seem to need everything but the kitchen sink to actually run it - just under 50 separate jar files - taking up 16 MB and including the Ant jar, 10 Maven jars, and the drools compiler jar even though I'm not supposed to be compiling anything, and I'm certainly not trying to use Maven or Ant! Of the 67 Jar files in the distribution nearly all seem directly linked to Maven, and very few (I'd judge from the approach below about 10 to 15) actually have anything to do with a rules runtime.
Going back to an example I built with Drools 5, several years back, I came up with the following code to reload a drl file I'd compiled separately using the Knowledge Base APIs:
private KnowledgeBase readSavedKnowledgeBase() throws Exception {
byte[] serializedKb = (byte[]) deserialize(RULES_SER);
ByteArrayInputStream bais = new ByteArrayInputStream(serializedKb);
DroolsObjectInputStream ois = new DroolsObjectInputStream(bais);
KnowledgeBase kbase = (KnowledgeBase) ois.readObject();
ois.close();
return kbase;
}
This works fine with 6.1. I only need 9 jars, (and I don't need the compiler jar) - and my run-time is a fairly reasonable 5MB. The down side is that Eclipse is unhappy since the KnowledgeBase class is now deprecated.
Could someone point the way to allowing me to get the same result using non-deprecated classes but without all the baggage of Maven and so on which I don't want or need to actually run some rules?

Some 6.x code for building:
KieServices ks = KieServices.Factory.get();
KieFileSystem kfs = ks.newKieFileSystem();
FileInputStream fis = new FileInputStream( "sale/sale.drl" );
kfs.write( "src/main/resources/sale.drl",
ks.getResources().newInputStreamResource( fis ) );
KieBuilder kieBuilder = ks.newKieBuilder( kfs ).buildAll();
Results results = kieBuilder.getResults();
if( results.hasMessages( Message.Level.ERROR ) ){
System.out.println( results.getMessages() );
throw new IllegalStateException( "### errors ###" );
}
KieContainer kieContainer =
ks.newKieContainer( ks.getRepository().getDefaultReleaseId() );
// CEP - get the KIE related configuration container and set the EventProcessing (from default cloud) to Stream
KieBaseConfiguration config = ks.newKieBaseConfiguration();
config.setOption( EventProcessingOption.STREAM );
KieBase kieBase = kieContainer.newKieBase( config );
// KieSession kieSession = kieContainer.newKieSession();
KieSession kieSession = kieBase.newKieSession();
You can serialize out the KieBase and back in for fast startup. I run this for various tests using the below CLASSPATH, but for execution you'll not need antlr, decisiontables, templates, and (maybe) others.
export CLASSPATH=".:$root/drools-core-${tag}.jar:$root/kie-api-${tag}.jar:$roo/kie-internal-${tag}.jar:$root/knowledge-internal-api-${tag}.jar:$root/drools-compiler-${tag}.jar:$root/antlr-runtime-3.5.jar:$root/ecj-4.3.1.jar:$root/mvel2-2.1.9.Final.jar:$root/drools-decisiontables-${tag}.jar:$root/drools-templates-${tag}.jar:$root/protobuf-java-2.5.0.jar:$root/slf4j-api-1.7.2.jar:$root/xstream-1.4.7.jar:$SLF4J"
For serialiazation and its counterpart use the usual mantra:
ObjectOutputStream out =
new ObjectOutputStream( new FileOutputStream( pkgPath ) );
out.writeObject( kieBase );
out.close();
//---------- In another program ---------------
ObjectInputStream in =
new ObjectInputStream( new FileInputStream( pkgPath ) );
#SuppressWarnings( "unchecked" )
KieBase kieBase = (KieBase)in.readObject();
in.close();

It only brings in Maven if you have kie-ci on the classpath, remove that and you will not have any maven. However you will also not have any dependency management or pom analysis - if you don't need those things, you don't need maven to compile. Without kie-ci it will fall back to a "light" pom.xml parser. You can still programmatically provide it the other kiemodulies it depends on.

Related

Can't generate jasper report on spring

I am trying to generate a PDF file using JasperReports, however, regardless of how I try it, it's giving me a NullPointerException.
https://community.jaspersoft.com/questions/520803/getting-null-pointer-exception-fillreport
Tried looking there, and changed the jasper properties file, but it didn't do anything and i'm still getting the same error.
Tried absolute paths, relative paths, getting resource as stream, nothing
This is the code i'm using to generate the report
public String generateInvoiceFor (Reservation reservation) throws JRException {
JasperReport jasperReport = JasperCompileManager.compileReport("I:\\anoranzaHopefullyFinal\\src\\main\\resources\\jasper\\FacturaFinalFinal.jrxml");
List<Reservation> reservations = reservationService.getAll();
JRBeanCollectionDataSource jrBeanCollectionDataSource = new JRBeanCollectionDataSource(reservations);
Map<String,Object> parameters = new HashMap<>();
parameters.put("Idparam", reservation.getId());
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, jrBeanCollectionDataSource);
JasperExportManager.exportReportToPdfFile(jasperPrint, "jasper/jasperOutput/Factura.pdf");
return "Report successfully generated #path= jasper/jasperOutput/";
}
Check your datasource and jasperPrint. If there is no problem try this.
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(
new SimpleOutputStreamExporterOutput("PDF NAME IS HERE.pdf"));
SimplePdfReportConfiguration reportConfig
= new SimplePdfReportConfiguration();
reportConfig.setSizePageToContent(true);
reportConfig.setForceLineBreakPolicy(false);
SimplePdfExporterConfiguration exportConfig
= new SimplePdfExporterConfiguration();
exportConfig.setMetadataAuthor("Auth name is here");
exportConfig.setEncrypted(true);
exportConfig.setAllowedPermissionsHint("PRINTING");
exporter.setConfiguration(reportConfig);
exporter.setConfiguration(exportConfig);
exporter.exportReport();

How to get the JUnit surefire report programatically

I need to use JUnitCore to run unit tests from a standalone jar test tool. I have added the surefire jars as dependencies and there I found the class org.apache.maven.surefire.junitcore.JUnitCoreRunListener. In this github this is a sample of its usage.
My intention is to get the xml report that would result from running maven without maven at runtime.
RunListener reporter = new JUnitCoreRunListener( new MockReporter(), new HashMap<String, TestSet>() );
JUnitCore jc = new JUnitCore();
jc.addListener( reporter );
Result r = jc.run( new Computer(), AppTest.class);
jc.removeListener( reporter );
System.out.println( r );
This is not working. What is the correct approach to get the XML output from that reporter?

GWT Spring Jasper Reports

I have an application built in GWT and Spring. I am trying to generate Jasper Reports on the server side. However when I execute the functionality, it hangs/stops at jasperDesign = JRXmlLoader.load(file_name); and does not respond or throw an exception. This means that my RPC call that triggers the report generation function does not return a response either (so the application hangs). However when I run the function in a normal java application it generates a report without any problem. What could be the issue? I am using JasperReports version 5.6.0. My java function:
public StandardServerResponse printReport(List<Object> items) {
StandardServerResponse response = new StandardServerResponse();
String file_name = null;
Map<String, Object> parameters;
JasperDesign jasperDesign;
JasperReport jasperReport;
JasperPrint jasperPrint;
try {
for (Object obj: items) {
parameters = new HashMap<String, Object>();
parameters.put("id_in", obj.getId());
file_name = "G:\\myreport.jrxml";
jasperDesign = JRXmlLoader.load(file_name); //application stops here
jasperReport = JasperCompileManager.compileReport(jasperDesign);
jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource.getConnection());
JasperExportManager.exportReportToPdfFile(jasperPrint, "G:\\report.pdf");
}
response.setSuccess(true);
} catch (Exception ex) {
ex.printStackTrace();
response.setSuccess(false);
}
return response;
}
I finally solved my problem after many long days of debugging :-).
I had these two jars in my WEB-INF/lib folder.
jasperreports-functions-5.6.0-SNAPSHOT.jar
jasperreports-fonts-5.6.0.jar
I removed them and the app worked. I still don't understand why they would cause a problem though.
I also changed my code to work with a .jasper extension and directly called JasperRunManager.runReportToPdfFile(file_name, "S:\\output_report.pdf", parameters, connection);
Thanks a lot Darshan Lila for trying, I really appreciate. Hope this helps someone.

How to load jasperreports resourcebundle at runtime?

Is it possible with jasper Reports to load a ResourceBundle (for i18n) at runtime?
I want to create a report from a jrxml file (for example c:\reports\report.jrxml)
with my labels in the properties file located at (c:\messages\report.properties).
I only found example where the property file is in the classloader.
Thanks
John Ferguson's blog mentions that the trick is to override the REPORT_RESOURCE_BUNDLE parameter with a custom ResourceBundle instance.
// Compiling the report is not a necessary step; prefer using .jasper files
// that have been pre-compiled to avoid this compilation step.
//
JasperDesign jasperDesign = JasperManager.loadXmlDesign("Report.jrxml");
JasperReport jasperReport = JasperManager.compileReport(jasperDesign);
Map parameters = new HashMap();
parameters.put("REPORT_LOCALE",LocaleManager.currentLocale());
parameters.put("REPORT_RESOURCE_BUNDLE",resourceBundle);
Connection conn = DBConnectionFactory.getConnection();
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport,
parameters,
conn);
The resourceBundle can come from anywhere. For example:
try(FileInputStream fis = new FileInputStream("/tmp/report.properties")) {
ResourceBundle resourceBundle = new PropertyResourceBundle(fis);
// Pass resourceBundle into the report, as shown above.
}
loading bundle from resources package:
ResourceBundle bundle=ResourceBundle.getBundle("/reports/bundles/bundle",Locale.CANADA_FRENCH);
filling report::
params.put("REPORT_RESOURCE_BUNDLE", bundle);
JasperPrint jasPrint = JasperFillManager.fillReport(reportStream, params, data);

Framework for generating BPEL in runtime?

I need to generate BPEL XML code in runtime. The only way I can do it now is to create XML document with "bare hands" using DOM API. But there must be a framework that could ease such work incorporating some kind of object model.
I guess it should look something like this:
BPELProcessFactory.CreateProcess().addSequence
Do you know any?
The Eclipse BPEL designer project provides an EMF model for BPEL 2.0. The generated code can be used to programmatically create BPEL code with a convenient API.
In case anyone stumbles upon this.
Yes this can be done using the BPEL Model.
Here is a sample piece of code which generates a quite trivial BPEL file:
public Process createBPEL()
{
Process process = null;
BPELFactory factory = BPELFactory.eINSTANCE;
try
{
ResourceSet rSet = new ResourceSetImpl();
rSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
.put("bpel", new BPELResourceFactoryImpl());
File file = new File("myfile.bpel");
file.createNewFile();
String filePath = file.getAbsolutePath();
System.out.println(filePath);
AdapterRegistry.INSTANCE.registerAdapterFactory( BPELPackage.eINSTANCE, BasicBPELAdapterFactory.INSTANCE );
Resource resource = rSet.createResource(URI.createFileURI(filePath));
process = factory.createProcess();
process.setName("FirstBPEL");
Sequence seq = factory.createSequence();
seq.setName("MainSequence");
Receive recieve = factory.createReceive();
PortType portType = new PortTypeProxy(URI.createURI("http://baseuri"), new QName("qname"));
Operation operation = new OperationProxy(URI.createURI("http://localhost"), portType , "operation_name");
recieve.setOperation(operation);
Invoke invoke = factory.createInvoke();
invoke.setOperation(operation);
While whiles = factory.createWhile();
If if_st = factory.createIf();
List<Activity> activs = new ArrayList<Activity>();
activs.add(recieve);
activs.add(invoke);
activs.add(if_st);
activs.add(whiles);
seq.getActivities().addAll(activs);
process.setActivity(seq);
resource.getContents().add(process);
Map<String,String> map = new HashMap<String, String>();
map.put("bpel", "http://docs.oasis-open.org/wsbpel/2.0/process/executable");
map.put("xsd", "http://www.w3.org/2001/XMLSchema");
resource.save(map);
}
catch(Exception e)
{
e.printStackTrace();
}
return process;
}
The dependencies require that you add the following jars to the project's build path from the plugins folder in eclipse installation directory:
org.eclipse.bpel.model_*.jar
org.eclipse.wst.wsdl_*.jar
org.eclipse.emf.common_*.jar
org.eclipse.emf.ecore_*.jar
org.eclipse.emf.ecore.xmi_*.jar
javax.wsdl_*.jar
org.apache.xerces_*.jar
org.eclipse.bpel.common.model_*.jar
org.eclipse.xsd_*.jar
org.eclipse.core.resources_*.jar
org.eclipse.osgi_*.jar
org.eclipse.core.runtime_*.jar
org.eclipse.equinox.common_*.jar
org.eclipse.core.jobs_*.jar
org.eclipse.core.runtime.compatibility_*.jar

Resources