Ok... I think I know what is happening..
Background: each element in a package (rule, process, function, etc..)
is mapped to the resource it was defined in. Resources can then be monitored
for changes and the KB will be updated as appropriate.
When the KnowledgeAgent (KA) is created with an initial KB,
it will not rebuild the mapping between elements and existing resources, but
"trust" the preexisting mapping and monitor the resources declared by
the KB.
The KA only builds the mapping itself when it's actively applying a
changest to
modify the KB it's managing.
This said, here's what's probably happening in your case:
You create a KB "manually" using the KnowledgeBuilder, which downloads
the serialized package from Guvnor. The elements in this package have been
created and mapped to the "internal" (guvnor-side) reader resource, not the
URLResource that Guvnor would expose the package at.
Of course this resource is not serializable, but is not replaced by Guvnor,
so the client gets a PKG whose elements are mapped to a "void" resource.
The KnowledgeBuilder does not override it - actually, it wouldn't
override it
even if it was NULL!.
Now, the KA won't either.. since 1) it trusts the preexisting mapping
in the KB and 2) it never sees the UrlResource in the first place.
In summary, when the KA tries to monitor an element's resource for changes,
it will try to use the void reader resource rather than the urlResrouce,
which explains why you don't get the desired updates.
The natural workaround is to initialize the KA with an empty KnowledgeBase.
Then, let the KA manage the resources by applying a changeset, as shown
in the documentation.
Best
Davide
IMHO, this behavior borderlines a bug. The KB on the client side is
essentially
corrupted, since rules, type declarations, etc.. are loaded with a "nulled"
resource. Currently, PackageBuilder.addPackageFromInputStream does not
override the resources in the PKG elements with the PKG itself.
I think I see the idea: if the PKG has been used for persistence, the
behavior
is correct. But here the PKG is used for distribution, so it should be
overridden.
Options are:
- always override
- always override if the PKG comes from a UrlResource (probably not robust)
- override if element.resource is null (likely to be impossible) OR
null-equivalent,
as in this case
- never override ( the current approach )
- other ideas?
On 05/02/2013 01:52 AM, riri wrote:
Here is the code I am using to create the knowledge base, knowledge
agent and
to retrieve the resources:
public static KnowledgeBase createKnowledgeBase(List<DroolsResource>
resources,
EventProcessingOption eventProcessingOption)
{
KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder();
for (DroolsResource resource : resources)
{
logger.info("Resource: " + resource.getType() + ", path type="
+ resource.getPathType() + ", path=" + resource.getPath());
switch (resource.getPathType())
{
case CLASSPATH:
builder.add(ResourceFactory.newClassPathResource(resource.getPath()),
resource.getType());
break;
case FILE:
builder.add(ResourceFactory.newFileResource(resource.getPath()),
resource.getType());
break;
case URL:
UrlResource urlResource = (UrlResource) ResourceFactory
.newUrlResource(resource.getPath());
if (resource.getUsername() != null)
{
logger.info("Setting authentication for: " +
resource.getUsername());
urlResource.setBasicAuthentication("enabled");
urlResource.setUsername(resource.getUsername());
urlResource.setPassword(resource.getPassword());
}
builder.add(urlResource, resource.getType());
break;
default:
throw new IllegalArgumentException(
"Unable to build this resource path type.");
}
}
if (builder.hasErrors()) {
throw new RuntimeException(builder.getErrors().toString());
}
KnowledgeBaseConfiguration conf =
KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
// setting the STREAM option
conf.setOption(eventProcessingOption);
// modify the default identity compare mode to equality
conf.setOption(AssertBehaviorOption.EQUALITY);
KnowledgeBase knowledgeBase =
KnowledgeBaseFactory.newKnowledgeBase(conf);
knowledgeBase.addKnowledgePackages(builder.getKnowledgePackages());
return knowledgeBase;
}
public static KnowledgeAgent createKnowledgeAgent(String
knowledgeAgentName, KnowledgeBase knowledgeBase)
{
KnowledgeAgentConfiguration aconf =
KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
aconf.setProperty("drools.agent.newInstance", "false");
KnowledgeAgent kagent =
KnowledgeAgentFactory.newKnowledgeAgent(knowledgeAgentName, knowledgeBase,
aconf);
ResourceFactory.getResourceChangeScannerService().start();
ResourceFactory.getResourceChangeNotifierService().start();
return kagent;
}
public DroolsResource getGuvnorResource(User user)
{
String packageName = user.getUsername();
String guvnorBinaryResourceUrl =
"http://127.0.0.1:8080/guvnor/rest/packages/" + packageName +
"/binary";
return new DroolsResource(guvnorBinaryResourceUrl, ResourcePathType.URL,
ResourceType.PKG, credentials.getUserPrincipal().getName(),
credentials.getPassword());
}
Where the DroolsResource is a custom class to hold information about a
resource:
public class DroolsResource
{
private String path;
private ResourcePathType pathType;
private ResourceType type;
private String username = null;
private String password = null;
//getters, setters and constructors
}
To initialize the environement I just call the method to create the
knowledge base once I have the DroolsResource and then the method to create
the knowledge agent. Afterwards I create a statefull knowledge session using
the getKnowledgeBase() of the agent. Would the problem be the Guvnor url
that I am using? I used the rest version since it sais that it builds the
package automatically. Or the fact that the url is not in a change-set.xml
file?
When I run the session the first time (via the fireUntilHalt() in a separate
thread), rules get executed correctly and I call the halt() method to stop
it. If I then go and change a rule in the package and restart the session
then no changes are taken into account. Is the way I am executing the
sessions a problem? I do not want to recreate a new session every time since
I would have to reinsert all the facts, so I retrieve the session from the
knowledge base. I dispose of the session when the application is shut down.
I am new at this so I might be overlooking an important aspect.
Many thanks for all your help.
--
View this message in context:
http://drools.46999.n3.nabble.com/Re-rules-users-KnowledgeAgent-to-update...
Sent from the Drools: User forum mailing list archive at
Nabble.com.
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users