You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@servicemix.apache.org by James Strachan <ja...@gmail.com> on 2006/08/24 12:18:37 UTC

Conversational POJOs (was Re: Thoughts on a JBI POJO Engine

Just another brainstorm; I thought we should split this thread into
two; one for POJOs & mapping to JBI/JSR 181/AnDI and another to doing
conversations/orchestration/workflow.

So we've got BeanFlow for writing POJO based workflows; I was
wondering about how we could link that to JBI POJOS (supporting JBI /
JSR 181 / AnDI annotations etc).

Here's a quick brainstorm. The basic idea is to introduce a little
POJO wrapper for an asynchronous JBI message exchange (a
request-response or one way which could take time to complete etc).
This POJO would implement the Activity interface from BeanFlow so we
could easily use it in a full workflow if desired. Then this POJO
would also be tied to a specific Destination. Also this POJO would be
injected by the container.

Many workflows only require making a single request on a number of
different endpoints - e.g. the following example talks to A, then
after thats complete, talks to B and C in parallel then when both of
those complete we talk to D. If we need to keep re-requesting services
we could reset the ExchangeActivity maybe (or just go back to using
the Destination directly).

So here's a little example...

public class MyWorkflow {

  @Endpoint("service:foo") ExchangeActivity a;
  @Endpoint("jms://activemq/foo.bar") ExchangeActivity b;
  @Endpoint("service:bar") ExchangeActivity c;
  @Endpoint("service:xyz") ExchangeActivity d;

   @PostConstruct
   public void start() {
     NormalizedMessage message = a.createInMessage();
     message.setContent(new StringSource("<hello>world!</hello>"));
     ...
     a.request(message);
  }

  @Join
   public void onJoin(Activity exchange) {
      if (exchange == a) {
        // lets fire off to be and c
        b.request(createRequestB());
        c.request(createRequestC());
     }
     else if (b.isComplete() && c.isComplete()) {
       d.request(createRequestD());
    }
}


So requests are all asynchronous and we get a join callback when any
of the exchanges (or other arbirary activities) change
(complete/fail/timeout) so we can perform whatever join conditions we
need.

I did ponder about using annotations to create methods for
'aComplete()' and 'bAndCComplete()' but it seems easier to use Java
code for boolean logic. The downside of this though is its not easily
possible to create tooling visualisations of this workflow.

We could use some kind of join language though so we could rewrite the
join logic as

@Join("a")
public void completedA() {
        b.request(createRequestB());
        c.request(createRequestC());
}

@Join("b and c")
public void completedBandC() {
       d.request(createRequestD());
}

where the  of a, b, c would resolve to properties or fields which must
return instances of type Activity from BeanFlow.

The nice thing about this use of @Join is that it would work with any
BeanFlow construct, JBI or otherwise. Then we are only really
introducing a POJO ExchangeActivity and an annotation to inject it
based on a destination URI (@Endpoint).

Am not particularly wedded to the names of ExchangeActivity and
@Endpoint but it was the best I could come up with without having too
much coffee yet. We might want to split @Endpoint into a couple of
tags as we might want to include both the endpoint URI and the type of
the request, InOut/InOnly etc.

Thoughts?
-- 

James
-------
http://radio.weblogs.com/0112098/

Re: Conversational POJOs (was Re: Thoughts on a JBI POJO Engine

Posted by James Strachan <ja...@gmail.com>.
On 8/24/06, Guillaume Nodet <gn...@gmail.com> wrote:
> Just on a side note, will try to take a depper look at this mail later.
>
> While I think the beanflow concept is cool and very usefull, I think there
> are some design problems.
> I have tried to fix http://issues.apache.org/activemq/browse/SM-439
> without luck.  If you could have a look ;)

Will do :)


> I think the main problem in beanflow is that the workflow is controlled
> from the inside and not managed controlled by an engine.

Agreed. In my mail I was kinda just thinking of using one or two
interfaces from BeanFlow (just the Activity interface really) and then
allowing an engine to do all the work rather than writing BeanFlow
workflows.


> This would also enable using persistence so that flows could
> be used transactionally.  For example, if you want to include
> the whole flow inside a transaction, you can obiously not spawn
> a thread and perform a join later.  The different steps in the flow
> have to be performed sequentially.

Agreed!


> The flow could be described using annotations (so quite static)
> or maybe dynamically using an injected interface which would
> allow to fork / join tasks, while keeping these tasks under
> the control of the engine.
>
> Btw, I love the @Join("a and b") annotation.
> I have previsouly thought to a less powerfull
>   @Join(steps = { "a", "b" }),
> but you could not have some magical expressions, like
>    @Join("a + b + c >= 2")
> which should be the same as
>    @Join("quorum(a, b, c)")
>
> :)

Nice! :)

I guess we could have a kinda SQL 92 type join language (like JMS
selectors) which allows a few functions like quorum and so forth.

-- 

James
-------
http://radio.weblogs.com/0112098/

Re: Conversational POJOs (was Re: Thoughts on a JBI POJO Engine

Posted by Guillaume Nodet <gn...@gmail.com>.
Just on a side note, will try to take a depper look at this mail later.

While I think the beanflow concept is cool and very usefull, I think there
are some design problems.
I have tried to fix http://issues.apache.org/activemq/browse/SM-439
without luck.  If you could have a look ;)

I think the main problem in beanflow is that the workflow is controlled
from the inside and not managed controlled by an engine.
This would also enable using persistence so that flows could
be used transactionally.  For example, if you want to include
the whole flow inside a transaction, you can obiously not spawn
a thread and perform a join later.  The different steps in the flow
have to be performed sequentially.

The flow could be described using annotations (so quite static)
or maybe dynamically using an injected interface which would
allow to fork / join tasks, while keeping these tasks under
the control of the engine.

Btw, I love the @Join("a and b") annotation.
I have previsouly thought to a less powerfull
  @Join(steps = { "a", "b" }),
but you could not have some magical expressions, like
   @Join("a + b + c >= 2")
which should be the same as
   @Join("quorum(a, b, c)")

:)

On 8/24/06, James Strachan <ja...@gmail.com> wrote:
>
> Just another brainstorm; I thought we should split this thread into
> two; one for POJOs & mapping to JBI/JSR 181/AnDI and another to doing
> conversations/orchestration/workflow.
>
> So we've got BeanFlow for writing POJO based workflows; I was
> wondering about how we could link that to JBI POJOS (supporting JBI /
> JSR 181 / AnDI annotations etc).
>
> Here's a quick brainstorm. The basic idea is to introduce a little
> POJO wrapper for an asynchronous JBI message exchange (a
> request-response or one way which could take time to complete etc).
> This POJO would implement the Activity interface from BeanFlow so we
> could easily use it in a full workflow if desired. Then this POJO
> would also be tied to a specific Destination. Also this POJO would be
> injected by the container.
>
> Many workflows only require making a single request on a number of
> different endpoints - e.g. the following example talks to A, then
> after thats complete, talks to B and C in parallel then when both of
> those complete we talk to D. If we need to keep re-requesting services
> we could reset the ExchangeActivity maybe (or just go back to using
> the Destination directly).
>
> So here's a little example...
>
> public class MyWorkflow {
>
>   @Endpoint("service:foo") ExchangeActivity a;
>   @Endpoint("jms://activemq/foo.bar") ExchangeActivity b;
>   @Endpoint("service:bar") ExchangeActivity c;
>   @Endpoint("service:xyz") ExchangeActivity d;
>
>    @PostConstruct
>    public void start() {
>      NormalizedMessage message = a.createInMessage();
>      message.setContent(new StringSource("<hello>world!</hello>"));
>      ...
>      a.request(message);
>   }
>
>   @Join
>    public void onJoin(Activity exchange) {
>       if (exchange == a) {
>         // lets fire off to be and c
>         b.request(createRequestB());
>         c.request(createRequestC());
>      }
>      else if (b.isComplete() && c.isComplete()) {
>        d.request(createRequestD());
>     }
> }
>
>
> So requests are all asynchronous and we get a join callback when any
> of the exchanges (or other arbirary activities) change
> (complete/fail/timeout) so we can perform whatever join conditions we
> need.
>
> I did ponder about using annotations to create methods for
> 'aComplete()' and 'bAndCComplete()' but it seems easier to use Java
> code for boolean logic. The downside of this though is its not easily
> possible to create tooling visualisations of this workflow.
>
> We could use some kind of join language though so we could rewrite the
> join logic as
>
> @Join("a")
> public void completedA() {
>         b.request(createRequestB());
>         c.request(createRequestC());
> }
>
> @Join("b and c")
> public void completedBandC() {
>        d.request(createRequestD());
> }
>
> where the  of a, b, c would resolve to properties or fields which must
> return instances of type Activity from BeanFlow.
>
> The nice thing about this use of @Join is that it would work with any
> BeanFlow construct, JBI or otherwise. Then we are only really
> introducing a POJO ExchangeActivity and an annotation to inject it
> based on a destination URI (@Endpoint).
>
> Am not particularly wedded to the names of ExchangeActivity and
> @Endpoint but it was the best I could come up with without having too
> much coffee yet. We might want to split @Endpoint into a couple of
> tags as we might want to include both the endpoint URI and the type of
> the request, InOut/InOnly etc.
>
> Thoughts?
> --
>
> James
> -------
> http://radio.weblogs.com/0112098/
>



-- 
Cheers,
Guillaume Nodet