-
15. Re: RuleService - output
dward Sep 20, 2012 11:24 AM (in response to magick93)I must have misunderstood what you are trying to do. I thought you were saying you didn't know how to insert facts using SwitchYard.
Are you instead asking how can you get facts that are inserted within the rules out of the executing session, using SwitchYard?
If that's the case, then every fact that you insert should also be added to a global variable. Here is an example doing this:
class PolicyHolder {
Collection<Policy> getPolicies();
}
<implementation.rules>
<globals>
<mapping expression="path.to.your.policyHolder" variable="policyHolder"/>
</globals>
</implementation.rules>
global com.example.PolicyHolder policyHolder
rule "policy rule"
when
// whatever your conditions are
then
insert(policy);
policyHolder.getPolicies().add(policy);
end
After your rules are done executing, your PolicyHolder will have been populated with Policies.
The example is an explicit global mapping to the PolicyHolder. Of course, the SwitchYard Message content itself could be a PolicyHolder, in which cases the <globals> mapping wouldn't be necessary, as the Swithcyard Message is always available as a global variable in your rules.
So it would be like this:
global org.switchyard.Message message;
rule "policy rule"
when
// whatever your conditions are
then
insert(policy);
PolicyHolder policyHolder = (PolicyHolder)message.getContent();
policyHolder.getPolicies().add(policy);
end
The Message content is then available as the return object in an IN_OUT scenario.
Last variation is that instead of a Collection<Policy>, it could be a Map<String,Policy>, so you can dynamically add Policies by name in your rules. Same thing applies, though, that it needs to be a global mapping itself, or something contained within a global mapping.
Am I now understanding your issue properly?
-
16. Re: RuleService - output
magick93 Sep 20, 2012 12:39 PM (in response to dward)Hi David
Yes I think you are understanding, yes I am refering to inserting with a drools rule.
The problem now that I see is that we have several hundred rules, and we are using Guvnor.
Gunvor has built in support of easily adding of an insert or modify statement - which we are making use of.
Having to add:
PolicyHolder policyHolder = (PolicyHolder)message.getContent();
policyHolder.getPolicies().add(policy);
will require significant re-writing of rules, and the analysts would need to change how they use Guvnor (learn to add free-form drl - basically Guvnor has native support for inserting, logical insert and modify) - and I cant see this happening, easily.
If at all possible, it would great - and believe a more successful adoption of SwitchYard - if it were possible to support insert objects into Working Memory, and then have these available within SwitchYard.
-
17. Re: RuleService - output
dward Sep 20, 2012 1:40 PM (in response to magick93)The whole purpose of Globals in Drools is to have a shared space for data, and SwitchYard supports that. It is "the sanctioned way" of doing this sort of thing, rather than frameworks implementing their own mechanism. So I don't believe there is a limitation being imposed by SwitchYard here. (Not being defensive; just explaining why it is the way it is.)
I understand - and agree - that forcing analysts to learn DRL and modify lots of it is not a good idea. So... here's an option: Why not write some DSL that does what you need? The DSL could be short and sweet and human-readable, but under the covers does both the insert into working memory, as well as adding it to the global?
-
18. Re: RuleService - output
dward Sep 20, 2012 1:42 PM (in response to dward)Or you could write a function...
-
19. Re: RuleService - output
magick93 Sep 20, 2012 2:31 PM (in response to dward)yes thats right - a function would probably be easier.
The option of using a DSL is something that we are already considering. At this stage we are very interested - actually excited - about using SwitchYard. But we do have many rules, and want to avoid any re-writing - whether that be to DSL or even a function. Although a function would be easiers.
I accept the 'sanctioned' way for SwitchYard - using globals. But this is not the 'ride the sacred goat of happiness' way of drools - IMO. But. I'm still very joyous towards SwitchYard.
I will look at using a function.
Thanks David
-
20. Re: RuleService - output
dward Sep 20, 2012 3:24 PM (in response to magick93)Anton Hughes wrote:
'ride the sacred goat of happiness'
LOL.
Yeah, I understand. Thanks for your interest and feedback. It's very much appreciated.
-
21. Re: RuleService - output
jeffdelong Sep 20, 2012 6:21 PM (in response to dward)Anton,
You can still use working memory operations to insert facts into the working memory created by Switchyard. They are just not available to other Switchyard services without adding them to the message. This is no different from a typical Drools application. If you insert a fact into the working memory from the consequence of a rule, you first have to create the instance use a contructor and then call insert. In this case it is not available to the Java class that called it.
Only if you need to access these new facts as Java objects outside the working memory do you need to add them to the message, or use a global, etc.
So I would not expect you to have to re-write your rules.
Jeff
-
22. Re: RuleService - output
magick93 Jan 3, 2013 6:13 PM (in response to magick93)Hi Again
Apologize for reviving an old post, however I am still having trouble understanding how to get hold of output from a Rule Service.
Are there any examples in the quickstarts of getting values out of a RuleService?
-
23. Re: RuleService - output
dward Jan 4, 2013 10:55 AM (in response to magick93)Anton, I can whip together an example of this, but if it's okay with you, I'm gonna do it against 0.7 (which is available in Nexus, but just not yet publicized until we finish our final round of testing). I mention this because the configuration of the bpm and rules components has changed between 0.6 and 0.7. Considering I'm testing 0.7 anyway, I can use this as part of my manual testing. Does this sound okay with you?
-
24. Re: RuleService - output
magick93 Jan 4, 2013 11:51 AM (in response to dward)David, that would be greatly appreciated.
Many thanks
-
25. Re: RuleService - output
dward Jan 4, 2013 6:32 PM (in response to magick93)Anton,
I'm attaching a simple example I created using the SwitchYard 0.7 eclipse tooling. It shows the same rules switchyard service being executed via a java interface, and via a soap endpoint. In both cases, it is an IN_OUT service. Please refer to MyTest.java as a good starting point. In the first test, the service is invoked by passing in a Widget where the processed flag is false. In return, you get a Widget where the processed flag is true. Who processed it? MyService.drl, of course. In the second test, the same service is executed, but this time by sending a soap message in, and gettting a soap message back. Same thing happens, but obviously there is xml tranformation done by switchyard.
The key is in the action input mapping, where the message content is made available to the rules engine as a fact. (This is because it is an <inputs><mapping>. For it to be a global, it would be a <globals><mapping>, and a variable name would have to be assigned to it, and the drl would have to declare the global. But I digress...) Inside MyService.drl, you see that the rule is triggered simply by there being a Widget available in working memory. Then, the object is mutated by the consequence side of the rule. $widget.setProcessed(true). That same Widget, which is still the content of the message, is sent back by SwitchYard. This is really just one way of accomplishing "getting values out of a Rule Service".
Hope this helps,
David
-
switchyard-example.zip 16.3 KB
-
-
26. Re: RuleService - output
magick93 Jan 9, 2013 10:18 AM (in response to dward)Thanks David, I really appreciate you taking the time to help.
In your example, you have
<rules:actions>
<rules:action operation="process" type="EXECUTE">
<rules:globals/>
<rules:inputs>
<rules:mapping expression="message.content"/>
</rules:inputs>
</rules:action>
</rules:actions>
You are using Input. I dont see anything that is IN_OUT.
I see in the SOAP response that a widget is returned.
And I see that the service method is Widget process(Widget widget); - is this what determines that you return a widget, even though you have not specified output statement, eg
<rules:outputs>
<rules:mapping expression="NewExpression"/>
</rules:outputs>
Questions
- Can I pass more than one parameter to a rule service?
- In your example you are not using the output settings. When are these useful / needed?
- message.content can be cast as a widget - correct?
- If yes, then when using a global, how can I cast an inner type of a complex object to a drools global?
- I noticed, at least in the 0.7 editor, that input, output and global all have the same options for scope - IN, OUT and EXCHANGE. Is IN_OUT missing? Or is that what EXCHANGE is?
Again, thank you for your help - hope I am not taking too much of your time, or trying your patience.
-
27. Re: RuleService - output
magick93 Jan 9, 2013 8:11 PM (in response to magick93)Hi again David
I've been playing around with your sample.
And while I can get it work, when I modify it slightly, and pass in a new object, see below, the rule does not fire.
package com.example.switchyard.switchyard_example;
import java.util.List;
public class Widgets {
private List<Widget> widgets = null;
public List<Widget> getWidgets() {
return widgets;
}
public void setWidgets(List<Widget> widgets) {
this.widgets = widgets;
}
}
And the rule now looks like:
package com.example.switchyard.switchyard_example
import com.example.switchyard.switchyard_example.Widgets
rule "MyService"
when
$widgets : Widgets()
then
System.out.println("********** WIDGETS **********");
end
And I changed the interface to be:
package com.example.switchyard.switchyard_example;
public interface MyService {
public Widgets process(Widgets widgets);
}
I cant understand why it would work with Widget, but with a new class - Widgets, that contains a list - it does not.
Do you have any ideas?
Thanks
-
28. Re: RuleService - output
dward Jan 10, 2013 12:06 PM (in response to magick93)Anton,
Don't confuse ExchangePattern (which has IN, OUT, IN_OUT) with Scope (which as IN, OUT, EXCHANGE). An ExchangePattern describes the message interaction between participants (ie: client and server), a Scope describes the applicability of Properties within a Context.
Both the java service interface (which has a return value and is invoked with the invoker.sendInOut), and the soap wsdl (which defines both input and output), describe the service as IN_OUT. However that's not how the return parameters is determined. In the absence of specifying an <outputs><mapping>, the code defaults to sending out the same content that was sent in (the modified Widget). So that's how that worked out. Again, there are multiple ways to peel this onion (and I don't have the bandwidth to code all of them for you). This is just one way.
To answer your specific questions:
- Yes. Multiple <mapping>s can be placed under <inputs>.
- Use <outputs> when you want to be specific what gets outputted rather than depending on default behavior.
- message.content (or the result of any expression) can be anything, but you are responsible to make sure it is of the correct type before it gets cast.
- You don't do the casting. Reflection is used. Just make sure your MVEL expression results in the appropriate object of the appropriate type (the type you declared in the drl global)
- See my note above about ExchangePattern vs. Scope.
David
-
29. Re: RuleService - output
dward Jan 10, 2013 9:29 AM (in response to magick93)1 of 1 people found this helpfulThere could be multiple reasons why your change didn't work:
- Did you update your client (invoking) code to match?
- If using SOAP, did you update the WSDL to match (as well as the soap-request.xml and soap-response.xml files)?
- Did you update the application's transformation code to match?
That's just a few right off the top of my head.