ReaderInterface

Drools 2 provided several convenience APIs for loading DRLs; where you could specify URL, InputSource, InputStream and Reader. In reality this just created bloat and larger API that we had to maintain as internal APIs changed. For Drools 3 we have standardised on Reader, leaving it to the user to pass the Reader instance.

 

This page is for those not familiar with the Reader interface.

http://java.sun.com/j2se/1.4.2/docs/api/java/io/Reader.html

 

The Reader interface is implemented by the following classes:

 

BufferedReader, LineNumberReader, CharArrayReader, InputStreamReader, FileReader, FilterReader, PushbackReader, PipedReader, StringReader, Writer

 

URL is able to return an InputStream with the openStream() method. Looking at the implementations above you can see there is an InputStreamReader, thus we can create a Reader instance from a URL as shown below:

 

    PackageBuilder builder = new PackageBuilder();
    URL url = new URL("http://domain.com/path/file.drl");                
    Reader reader = new InputStreamReader( url.openStream() );
    builder.addPackageFromDrl( reader );

While File does not open an InputStream thre is already a Reader implementation for handling Files:\

    PackageBuilder builder = new PackageBuilder();
    File file = new File("/path/file.drl") ;     
    Reader reader = new FileReader( file );     
    builder.addPackageFromDrl( reader );

 

Quite often it's convenient to place the drl file in the classpath to allow the classloader to locate the drl and open an InputStream to the resource. You should read the following article first "[How to read/load things from your classpath|http://www.javaworld.com/javaqa/2003-08/01-qa-0808-property_p.html]".

    PackageBuilder builder = new PackageBuilder();
    InputStream inputStream = MyClass.class.getResourceAsStream( "file.drl" );
    Reader reader = new InputStreamReader( inputStream );
    builder.addPackageFromDrl( reader );

 

 

Example in a production app server

The following example, provided by Schimmoeller, hows how it worked for him in WebSphere app server:

 

                        try {
                                    PackageBuilder builder = new PackageBuilder();
                                    InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream( sFile);
                                    if ( is == null)
                                                //if it is null try this way. Junit works using this way, WAS doesn't.
                                                is = System.class.getResourceAsStream(sFile);
                                                if(is == null)
                                                            throw new Exception("Failed to get InputStream for file: "+sFile);
                                    InputStreamReader isr = new InputStreamReader(is);
                                    if ( isr == null)
                                        throw new Exception("Failed to get InputStreamReader for file: "+sFile);
                                    builder.addPackageFromDrl(isr);

                                    Package pkg = builder.getPackage(); 
                                    ruleBase = RuleBaseFactory.newRuleBase();
                                    ruleBase.addPackage( pkg ); //can have multiple packages if you like...

                                    workingMemory = ruleBase.newWorkingMemory();

                        } catch (Exception e){
                            if (logger.isDebugEnabled() ) {
                                logger.debug("Init Method threw this exception.", e);
                            }
                                    throw new OpersException ( e.toString());
                        }