13 Replies Latest reply on Oct 13, 2009 4:53 PM by jeffdelong

    Supporting entry-point

    kconner

      We are intending to extend the BusinessRulesProcessor to support the entry-point API, as part of the following task.

      https://jira.jboss.org/jira/browse/JBESB-2273

      We need to get a better understanding of what is possible as well as what needs to supported, and are intending to discuss this with the drools team at J1 next week.

      In the meantime it would be good to get others opinions of what needs to be done, for example Jeff added the following comment to the JIRA.

      Jeff DeLong - 27/May/09 01:08 PM

      There is a little more to this potentially than just configuring the names of a entry points in a single service. Entry points are relative to the StatefulKnowledgeSession. They allow for multiple event streams to populate the working memory. So for example the Order service could be configured to use the OrderStream, and a Customer service would be configured to use the CustomerStream. A third service would then be configured to create the StatefulKnowledgeSession and place this object in some location where it could be looked up and used to create the entry points by the other two services. This capability is perhaps not necessary as part of the Tech Preview, but should be kept in mind when designing the entry point logic.

        • 1. Re: Supporting entry-point
          beve

          As an example of entry point usage (from the Drools Fusion User Guide):

          rule "apply fee on withdraws on branches"
          when
           WithdrawRequest( $ai : accountId, processed == true ) from entry-point "Branch Stream"
           CheckingAccount( accountId == $ai )
          then
           // apply a $2 fee on the account
          end

          Instead of inserting events directly into the working memory, you insert them into the entry point as shown in the following example:
          // create your rulebase and your session as usual
          StatefulKnowledgeSession session = ...
          
          // get a reference to the entry point
          WorkingMemoryEntryPoint atmStream = session.getWorkingMemoryEntryPoint( "ATM Stream" );
          
          // and start inserting your facts into the entry point
          atmStream.insert( aWithdrawRequest );

          By requesting the WorkingMemoryEntryPoint from the session we are able to insert our facts into it and this will be separate from the "default" working memory.

          In the ESB will want to give users the ability to use entry points in thier rules. To do this we need to let them specify which objects(facts) should be inserted in to the separate entry-points. Currently all are inserted in the the working memory (which I understand is simply a WorkingMemoryEntryPoint named "DEFAULT").

          Burr suggested that the following configuration option to be added:
          <object-path esb="body.TheOrderHeader" entry-point="OrderStream" />

          And this would result in something like this in the ESB code base:
          WorkingMemoryEntryPoint atmStream = session.getWorkingMemoryEntryPoint( "OrderStream" );
          atmStream.insert(orderHeader);
          


          Burr also mentioned that we should support the ability to set the startTimeStamp on an event:
          The date time stamp should be based on message DOB but perhaps overrideable here as well

          Every event in Drools has an associated timestamp assigned which by default is read from Session Clock.
          This startTimeStamp is assigned to the event at the time the event is inserted into the working memory.
          But you are given the opportunity to have Drools use a different timestamp, for instance the DOB of the ESB Message object, by specifying that the timestamp of the fact being should be used instead:
          @timestamp( <attributeName> )

          So if we specified dob as the attribute name, the object being inserted is expected to have a field named dob, and that that field contains the timestamp that will be used when creating the EventFactHandle.
          Just how this is going to look I don't know at the moment and I'd need to look into this and try it out.




          • 2. Re: Supporting entry-point
            beve

             

            There is a little more to this potentially than just configuring the names of a entry points in a single service. Entry points are relative to the StatefulKnowledgeSession. They allow for multiple event streams to populate the working memory. So for example the Order service could be configured to use the OrderStream, and a Customer service would be configured to use the CustomerStream. A third service would then be configured to create the StatefulKnowledgeSession and place this object in some location where it could be looked up and used to create the entry points by the other two services. This capability is perhaps not necessary as part of the Tech Preview, but should be kept in mind when designing the entry point logic.

            I'm trying to understand the usecase here and this is my take on this:
            1. OrderService (ESB service) uses rules and specifies an entry-point named "OrderEntryPoint".
            2. CustomerService (ESB service) uses rules and specifies an entry-point named "CustomerEntryPoint".
            3. DeliveryService (ESB service) uses rules and uses both of the above entry points.

            If this is correct then why would the OrderService and CustomerService not simply produce a Order and Customer object and pass them to the DeliveryService instead of making the DeliveryService operate on the same StatefulKnowledgeSession.
            Or have I totally misunderstood what you mean here :)
            Jeff, could you help me understand what you are after and the usecase you have in mind?

            Thanks,

            /Daniel


            • 3. Re: Supporting entry-point
              jeffdelong

              The use case is:

              1. OrderService (ESB service) specifies an entry-point named "OrderEntryPoint" and inserts order events into working memory.
              2. CustomerService (ESB service) specifies an entry-point named "CustomerEntryPoint" and inserts customer facts into working memory.
              3. DeliveryService (ESB service) uses rules, i.e., creates rulebase and working memory (statefulsession) used by used by both of the above entry points.

              The rationale for having multiple services use different entry points to insert different facts are:

              - Better performance. Some of these types of CEP applications have very high event rates (hundreds or more events per second). Funneling all the events to a single service (single queue) could be a performance bottleneck.

              - Cleaner design. Order service and Customer service are independent of each other. They might have other logic that is Order or Customer specific. For example the events may arrive in XML format and require transforming xml to Java and possibly adding some event related data (i.e., timestamp). Another service might be added to insert other types of facts without any impact to these two services.

              • 4. Re: Supporting entry-point
                tirelli

                Hi Jeff,

                Let me try to understand this architecture from a higher level point of view, not ESB or Drools specific:

                * the order service executes the business tasks it needs to execute, and also publishes events.

                * the customer service executes the business tasks it needs to execute, and also publishes events.

                * the delivery service is interested in the events published by the order service and by the customer service and uses them to take business decisions.

                Is that the case?

                From a business rules/event processing perspective, it seems to me that the delivery service should register itself to listen to the events from the other services, and tie the entry points to whatever publishing mechanism the other services use and not the other way around, but I don't know much about the current ESB architecture, so I will start doing some research right away.

                Can you plz comment on my point of view above?

                Thanks,
                Edson

                • 5. Re: Supporting entry-point
                  jeffdelong

                  Edson,

                  In the use case I describe the OrderService and CustomerService are not the producers of the events, the events are produced outside the ESB. The purpose of the use case is to describe how multiple services could receive different event streams and insert these different event streams into the same working memory. The purpose of have different services handle the different event streams, as mentioned in earlier post, would be performance / scalability and autonomy.

                  Also, could you comment at some point in this thread how greater scalability could be achieved by having the different services on different services in a cluster, and having the working memory distributed between the servers (if this is actually possible?)

                  Thanks,

                  Jeff

                  • 6. Re: Supporting entry-point
                    tirelli

                    Jeff,

                    Oh, I misunderstood you the first time. But yes, as usual you are right! That is how it was designed to be.

                    Regarding comments, the use of entry points for events is highly recommended because it reduces the matching space for the events and allows for concurrent feeding of data into the engine. End result is better performance and scalability, as you mentioned already.

                    On top of that, data transformation is also a possibility adding flexibility.

                    As of Drools 5, we don't support distributed working memory. In case the business case allows for any kind of data partitioning (you know, like sending all customers whose name starts with "A" to one server and "B" to the other server", then it is a good strategy, because it also helps reducing the match space. Of course, the same knowledgebase can be replicated to all servers and sessions instantiated in each of them.

                    Edson

                    • 7. Re: Supporting entry-point
                      camunda

                      Hi all.

                      What I currently don't understand in this scenario: Why doesn't every Service uses its own WorkingMemory? Isn't that conceptually the same what you describe?

                      And internal optimizations shouldn't be visible on the outside, right?

                      Or what have I missed? Somehow it seems I don't see the big picture yet. Can somebody maybe give a short business example?

                      Or maybe my knowledge of Drools Fusion is too limited, is there more info in the docs there?

                      Thanks and cheers
                      Bernd

                      • 8. Re: Supporting entry-point
                        jeffdelong

                        Bernd,

                        Fusion allows for events to come from different "event streams". In the example I posed (similar to the quickstart business_ruleservice_stateful) one object stream is of customers, the other is orders. Fusion does not really care how these events come in (e.g. JMS queues, etc.), but it does allow rules to be written against events from both streams. For example, the rules could calculate discounts based on order totals for a specific customer over some time period. So far this is just Drools CEP capabilities.

                        Now we want to add the ESB to the architecture to help manage the input streams, and deploy these rules as a service. So in what I described previously there could be three services, one that actually implements the business rules. and the other two to manage the input streams>

                        Your question is why does each service not have its own working memory? The answer is that we want both streams of objects in a single working memory so the rules operate against the combined set of facts. That is not the same as putting all the customers into one working memory and all the orders into a second working memory. If you did that with rules testing for the existence of both types of facts (like the rules in the quickstart), no rules would ever fire.

                        Internal optimizations should not be visible to the outside? Implementation details should not be visible outside of a service, but the functionality of a service is visible and why one service has one set of capabilities and another service has another set of capabilities would certainly be influenced by the desire to "optimize" services (i.e., it may not perform well if given too many tasks to perform). In this sense the allocation of capabilities to services is an "optimization"s.

                        So in this spirit, I proposed we provide the capabilities to create individual services, some whose capabilities are based on a managing the input stream of events of a certain type, and another to manage the actual rules execution. Perhaps these services could be better named the CustomerEventHandlingService and the OrderEventHandlingService, and the third service is the DiscountService. Yes this design is the result of an "optimization". But it might be a very reasonable optimization to make.



                        • 9. Re: Supporting entry-point
                          beve

                          Sorry for not replying earlier..some other stuff came up :(

                          The answer is that we want both streams of objects in a single working memory so the rules operate against the combined set of facts.

                          Are we talking about sharing a working memory between three services here?
                          OrderEventHandlingService and CustomerEventHandlingService would need to insert their events/facts into the same working memory that the DiscountService later uses.
                          I guess this could be done by passing the RuleBase along with the ESB Message instance in the pipeline but this could get messy given the current architecture.

                          Would a possible solution for this use case be that the OrderEventHandlingService did its required transformations and post the result to a JMS destination. The DiscountService Drools Fusion application then uses that destination as the one of its sources for event. It would do the same for the CustomerEventHandlingService.

                          What is the advantage of putting this business logic in an ESB service. This would mean that replacing the ESB would also affect you business application as opposed to "simply" configuring the new ESB with a transformation and a router to a JMS destination in this case.

                          Regards,

                          /Daniel





                          • 10. Re: Supporting entry-point
                            beve

                            Regarding the startTimestamp and using the ESB Message dob (entry time).

                            This can be done by declaring the Message as an event:

                            import org.jboss.internal.soa.esb.message.format.serialized.MessageImpl
                            
                            declare MessageImpl
                             @role( event )
                             @timestamp( properties.getProperty("org.jboss.soa.esb.message.time.dob") )
                            end
                            

                            Notice that we are specifying the concrete implementation and not the interface Message. I've not been able to get this to work by specifying the Message interface but will try to find out if that is possible.
                            Users can use the same approach as above to set the startTimeStamp. This can be done by setting a property on the ESB Message object and use that property name instead of "org.jboss.soa.esb.message.time.dob" above.

                            To find out the value of the Events startTimestamp we've added a log statement at debug level:
                            Event :org.jboss.internal.soa.esb.message.format.serialized.MessageImpl, startTimeStamp: 1246454582714
                            


                            Any thoughts on this?

                            Thanks,

                            /Daniel

                            • 11. Re: Supporting entry-point
                              jeffdelong

                              A couple things I wanted to bring over from and email thread:

                              1) We should add ESB exitPoint handling out-of-the-box that is declared in the ESB service configuration and has similar object mapping as the entry points. Basically it would take the object inserted into the exit point, create a new ESBMessage, copy the object into the ESB Message based on the exit point configuration, and send the ESB message to a configured "destination" (similar to CBR).

                              2) Is the BusinessRulesProcessor able to be configured for "StreamMode"? Most CEP applications will require StreamMode to enable sliding window support, garbage collection of expired facts, etc. This is really important (a necessity), and is turned on through the API.

                              • 12. Re: Supporting entry-point
                                jeffdelong

                                BusinessRulesProcessor needs additional configuration parameters as well as code to support CEP. These include:

                                EventProcessingOption with values of STREAM or CLOUD

                                The code to use this would be something like:

                                
                                kconfig = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
                                kconfig.setOption( EventProcessingOption.STREAM );
                                kbase = readKnowledgeBase(kconfig);
                                sconfig = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
                                sconfig.setOption( ClockTypeOption.get( ClockType.REALTIME_CLOCK.getId() ) );
                                ksession = kbase.newStatefulKnowledgeSession(sconfig, null);
                                
                                



                                Exit-points should also be supported. This would require configuration such as

                                
                                 <action class="org.jboss.soa.esb.actions.BusinessRulesProcessor" name="OrderCountHistory">
                                 <property name="ruleSet" value="OrderCount.drl"/>
                                 <property name="ruleReload" value="true"/>
                                 <property name="stateful" value="true"/>
                                 <property name="object-paths">
                                 <object-path entry-point="OrderEntryPoint" esb="body.TheOrderHeader"/>
                                 </property>
                                 <property name="exitPoint value="OrderExitPoint"
                                 <route-to destination-name="x" service-category="y" service-name="z"/>
                                 <property name="set-payload-location" value="orderResultPayload"/>
                                 </property>
                                 </action>
                                
                                


                                The configuration of multiple exit points should be allowed. Not sure how to add the set-payload-location but something like this is needed.

                                A class would then need to be added that implemented the ExitPointInterface such as:

                                
                                public class RulesCallbackInvoker implements ExitPoint
                                {
                                 public void insert(Object object) {
                                 try {
                                 ServiceInvoker invoker = new ServiceInvoker(service-category, service-name");
                                 Message requestMessage;
                                 requestMessage = MessageFactory.getInstance().getMessage(MessageType.JBOSS_XML);
                                 // add payload stuff
                                 requestMessage.getBody().add(object);
                                 invoker.deliverAsync(requestMessage);
                                 } catch (MessageDeliverException mde) {
                                 System.out.println("Eating this Exception: " + mde);
                                 }
                                 }
                                
                                }
                                
                                
                                


                                Then the BRP would need to add:

                                
                                RulesCallbackInvoker exit = new RulesCallbackInvoker();
                                KnowledgeRuntime kruntime = (KnowledgeRuntime) ksession.getEnvironment();
                                kruntime.registerExitPoint("exit-point", exit);
                                
                                



                                • 13. Re: Supporting entry-point
                                  jeffdelong

                                  Two other items we should discuss. The first is related to a discussion earlier in this topic on multiple services using the same StatefulKnowledgeSession, and that is the use of fireUntilHalt. We want an ESB Service to be able to create the KnowledgeBase, StatefulKnowledgeSession, etc, and then execute fireUntilHalt. This will cause the thread to block, and the rules engine will continue to process (in a separate thread). Either the same ESB Service, or different services (this is the relationship to the discussion earlier in the topic) can then receive messages / events and insert them into the working memory. However the absence of incoming event may still cause rules to fire.

                                  Second item is that the BusinessRulesProcessor should allow for configuration of a log file for audit logging. This audit log can then be read by the JBTools Drools Audit viewer. Which is very convenient for debugging.