Hi Guys,
I want to discuss a problem I have found when using the
combination of knowledge agent + classpathResources.
I will try to describe what am I doing first to give you some
context.
I'm deploying drools-camel-server in a Tomcat 7 container.
Inside the WEB-INF/classes directory I have some DRL files that
I want to use.
My knowledge-services.xml file declares the following kagent:
<drools:kagent id="kagent1" kbase="kbase1"
new-instance="false">
<drools:resources>
<drools:resource type="DRL" source="classpath:simple.drl"/>
...
</drools:resources>
</drools:kagent>
When spring parses this configuration file it creates a
KnowledgeAgent instance with a ChangeSet containing all the
listed resources.
The next step is to start ResourceChangeNotifierService
and ResourceChangeScannerService.
So far so good.
The problem:
The problem I'm having is not directly related to drools, but
I think it is quite easy to provide a solution for the people
that is in my same situation.
ClassPathResource is the class that represents a resource
defined as "classpath:"
This class has 2 important methods:
public long getLastModified(){
return this.classLoader.getResource( this.path
).openConnection().getLastModified();
}
public InputStream getInputStream(){
return this.classLoader.getResourceAsStream( this.path );
}
The first method is used by ResourceChangeScannerService to
check whether the resource has changed or not. It works fine.
When the resource in the filesystem changes, the scanner detects
the change without any problem.
The scanner ends up notifying the kagent about the change,
and the kagent passes the Resource to an instance of
KnowledgeBuilder.
An here is when things fail.
The kbuilder uses the second method of ClassPathResource
(getInputStream()) to get the content of the resource. In the
case of Tomcat (and probably some other environments), it seems
that the classloader (Tomcat's classloader) is using a cache. So
the InputStream returned doesn't reflect the current state of
the resource.
Long story short: the agent is notified about a change in the
resource, but the change is never applied to the kbase because
the kbuilder is unable to get it :P
Solutions:
The first solution is not to use classpath resources :). You
can use just url resources like
http:// or
file:/. But honestly,
when you have your rules inside your webapp, it is much
more comfortable and even manageable to avoid the use of real
paths.
What I was thinking about (I already have a working
prototype) is to create a new Resource type for these cases.
This resource type will let you define your resources present in
your classpath as usually but it will translate them to URL
Resource internally.
So, in the example above:
<drools:resource type="DRL" source="URLClasspath:simple.drl"/>
Opinions?
_______________________________________________
rules-dev mailing list
rules-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-dev