1 2 3 Previous Next 30 Replies Latest reply on Jan 10, 2013 11:47 AM by magick93 Go to original post
      • 15. Re: RuleService - output
        dward

        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

          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

            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

              Or you could write a function...

              • 19. Re: RuleService - output
                magick93

                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

                  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

                    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

                      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

                        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

                          David, that would be greatly appreciated.

                           

                          Many thanks

                          • 25. Re: RuleService - output
                            dward

                            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

                            1 of 1 people found this helpful
                            • 26. Re: RuleService - output
                              magick93

                              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

                              1. Can I pass more than one parameter to a rule service?
                              2. In your example you are not using the output settings. When are these useful / needed?
                              3. message.content can be cast as a widget - correct?
                              4. If yes, then when using a global, how can I cast an inner type of a complex object to a drools global?
                              5. 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

                                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

                                  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:

                                  1. Yes.  Multiple <mapping>s can be placed under <inputs>.
                                  2. Use <outputs> when you want to be specific what gets outputted rather than depending on default behavior.
                                  3. 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.
                                  4. 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)
                                  5. See my note above about ExchangePattern vs. Scope.

                                   

                                  David

                                  • 29. Re: RuleService - output
                                    dward

                                    There could be multiple reasons why your change didn't work:

                                    1. Did you update your client (invoking) code to match?
                                    2. If using SOAP, did you update the WSDL to match (as well as the soap-request.xml and soap-response.xml files)?
                                    3. Did you update the application's transformation code to match?

                                    That's just a few right off the top of my head.

                                    1 of 1 people found this helpful