REST vs. SOAP: Ops vs. Dev?

5 Comments

I’ve been reading a lot about REST, REST vs. SOAP, and security lately and came across this email thread post about how SOAP is so unsecure:

REST is not a security panacea. There is no silver bullet. All we can do is evaluate each layer’s *contribution* to security. SOAP’s is negative.It detracts from the security of the protocols that it runs on top of. If that were not the case then you would not be defensive about the idea that SOAP is designed to bypass firewalls.

I think I agree. SOAP does detract from the security of the protocols it runs on top of. Its trying to tunnel through port 80 and sneak past operations aversions to things like CORBA traffic. But is this such a bad thing? As far as this particular aspect of the SOAP vs. REST debate goes, what is the real underlying issue here? What I think it is is a matter of control. Ops doesn’t want CORBA/SOAP like requests because they can’t control what’s going back and forth over the wire. Control of the application has passed from operations to engineering.

From a developer point of view, we usually hate operations. You know the people I’m talking about. The control-freak paranoid dweebs that take at least a day to respond to any of our requests? They are the ones enforcing 10 character passwords that must be both alpha numeric, contain punctuation, upper and lower case, and that change once a month. They are the ones we have to sit in 3 hour meetings on whether to upgrade a certain library. It is like pulling teeth to get an operations guy to do anything beyond what they are trained to do. They are change resistant. They usually end up being blockers to our productivity. So its only natural that us developers would want to tunnel over HTTP to bypass these clowns. We have problems to solve, deadlines to meet, management breathing down our backs. They are the bureaucracy. Nobody is gonna come down on them when we can’t meet our deadlines.

On the flip side, operations is used to handling security issues. They have pre-existing tools and experience to deal with securing HTTP resources. Plus, managing the security aspect of an application is a tedious task. As developers, don’t we want ops handling this? Also, do we really want to waste the time training these idiots to a new technology? I guess it really depends how tech savvy and un-unionlike your ops guys are.

Side note:

Man, seems like I’m falling more and more into the REST camp. Its simpler. I want it to succeed. I’ve always disliked WS-*. But really, its probably because I’ve been focusing on pro-REST propaganda lately. I need to read some pro-SOAP articles.

RESTless, RESTFul, or RESTlike?

8 Comments

A couple of weeks ago I ran into my old mentor from my Iona days, Steve Vinoski. I was in shock. The guy I looked up to (and still do) for years, the guy who used to have sideburns the size of Elvis’s turned all “queer” on me. How could the guy who taught me everything I know about distributed systems go all RESTful on me? Telling me basically that he’s hooked and will never go back. I had read a little bit about REST earlier and was a little skeptical, but now I really had to take a closer second look.

Its funny, REST seems to be a bit like learning AOP. With AOP, one or two sentences just doesn’t articulate exactly what it is, or how you are supposed to use it. REST seems very similar in this regard. I’m almost getting it, but am still a bit fuzzy on how to do certain things. Since REST is more of an architectural style rather than a concrete API, I guess my slowness and confusion is a little justified. Or maybe its because RESTful articles and blogs seem to spend so much time trashing SOAP and saying how wa-wa-wa, “the Web is proof of why REST is so great”, in other words, “REST is great because of REST”, and very little time on actual examples is why it takes so much reading to get to the heart of it. I don’t know…. Maybe its all my CORBA baggage? All my Java EE baggage? Anyways, I don’t want to go into yet another, what is REST blog. If you want information on the definition of REST, the REST Wiki is a better source, found this link too. No, what I want to do is go through my own thought process to see if the REST way of things is the golden path. To do that I want to walk through some of the basic cornerstones of REST.

Use of URIs

One of the cornerstones of REST is to have resource location modeled as a URI. This seems like a no brainer. When we modeled our EJB 3.0 container on top of JBoss Remoting, which is URL based, our design became much simpler and things like request failover were much easier to write. Yeah, yeah, not every EJB has its own URI, but moving to URI based endpoints made implementation easier. So +1 for REST here. Its interesting though. How many times do we run into issues in Java EE land because it does not define unified addressing of its services? Its been a big roadblock in writing portable frameworks. WS-* has to have a whole spec on the subject, funny eh?

Uniform Interface

RESTful articles make a good analogy between SQL and the RESTFul architecture. I won’t paraphrase, but instead, directly quote:

It is nevertheless imperative to question our basic assumptions. Consider a similar debate taking place in the 1960s. A radical researcher within IBM states that it is incredibly inefficient for each application to determine for itself how to store, index and search its data. He proposes the concept of a “generalized database”. Clearly this “database” would not be as optimized for a particular problem domain as a specialized data store. But then imagine the interoperability benefits if many applications could access the same data in a uniform fashion. Then, later, another IBM researcher makes an even more ridiculous claim. He states that the vast majority of the structured information in the world can be manipulated with only four operations: SELECT/INSERT/UPDATE/DELETE. Ludicrous! What about AddCustomerRecord, DeleteCustomerRecord, InsertCustomerRecord, UpdateCustomerRecord?

The idea is, that in a RESTful architecture, everything is modeled in terms of resources accessed through a URI, and only 4 CRUD HTTP operations of GET, POST, PUT, and DELETE. From my perspective it is very counter-intuitive to express object interfaces in terms of 4 methods. Doesn’t make much sense as an object designer of local models, but for distributed systems, it does make a lot of sense I think. The CORBA in me balked at this idea, but then I thought about it a little more. How many of us had interoperability problems between different vendors or even different versions? Not only that, but in WS-* land most of the time you need to generate and compile stubs so that you can actually invoke on a web service. With REST, all you need is a HTTP client library. With WS-* you need the HTTP client library plus all the other junk. While HTTP is a mature, well-known, agreed-upon protocol, WS-* is such a moving target.

The question is, with the uniform interface of GET, PUT, POST, and DELETE, aren’t we just pushing the complexity to the content type? To the data that is being transferred and received? I had this very same argument with Vinoski. After thinking about it for awhile, i’ll say, that SOAP has the exact same problem. With SOAP, you still have to define and agree upon the API. The REST approach seems simpler because the protocol is set and simple, it doesn’t have the baggage of SOAP which is a protocol tunneled over another protocol (HTTP).

With the uniform interface approach, it does seem like it would be a lot easier to model security roles. It would just be assigning CRUD permissions really instead of assigning individual permissions to each method like you do in Java EE land. Caching is obvious because GET should mean the operation is idempotent. I don’t know…uniform interface and protocol seems pretty compelling.
Content-type

Don’t have a lot to say here other than, doesn’t XML schema sort of make SOAP obsolete?

Statelessness

I remember one of the students in the JBoss advanced training a few years ago talking about holding the state of a SFSB in the client proxy and transferring it to the server with every request. This would make sessions really failure proof and make the server fully scalable. An interesting idea. I was thinking that this could be done with Seam conversations as well, i’ll get into that in another blog in a few weeks or so. This idea of the client maintaining conversational state and passing it to the server is compelling, at least in theory. My last blog I talked the JBoss Business Activity service. What if the client was the coordinator for business activities and managed all compensations? The idea focuses around a quote I read in O’Reilly’s RESTful Web Services book:

The client should be in charge of managing its own path through the application

I’d like to dive into this more in future blogs on both Seam and BA. But all these ideas sound pretty RESTlike to me, at least in terms of statelessness.

That’s all for now

Well, I pretty much asked more questions than I answered here. Probably didn’t enlighten you, dear reader, at all about REST. Maybe confused you a little more? Or maybe I just showed how much I am confused? 🙂 Like AOP, I think I have to actually implement something RESTful before I actually understand if it is the right approach. Right now I’ll say my leaning are neither RESTless nor RESTFul, but rather RESTlike. Who knows, I’ll probably end up getting angry at both approaches(SOAP and REST) and design my own BURKEful way of doing things. Such a burkeful architecture would definately only work on JBoss though 😉 Let’s see what happens….

P.S.

It is fate. A day after I wrote this blog (I write a few days or weeks before I publish), this TSS article came out. I’m also taking a look at O’Reilly’s Restful Web Services book. I’ll let you know sometime how it goes.

Somebody forgot to tell Harrison

1 Comment

As you can see in the “About Me” section of this blog, this is my 15th season as a Patriots season ticket holder.  Last night was the Patriots pre-season home opener against the Tennessee Titans.  I have to tell you, in the past 14 years, last night was probably the best preseason game I have ever been to.  The thing is, somebody forgot to tell Rodney Harrison and the Pats defense that this was a preseason game.  Rodney was all over the field, with a nice pass deflection and a huge hit and sack on Vince Young. It was one of those hits that left the crowd going “oooooo”, “ohhhhhh”, “ouch”.  Poor Vince got nailed again and sacked hard by 38 year old Junior Seau.  A different series, the Titans got down the Patriots 2 yard line.  It felt like a playoff game, the crowd was screaming, the pats defense was pumped and stopped the Titans on downs 1-3.  The Titans decided to go for it on 4th down.  Vince Young rolled right, and looked like he had a clear path to the endzone.  How do I know this?  Well, my seats happened to be right in front of the action 15 rows back.  Just as Vince was about to dive into the endzone, a wall of patriots came out of nowhere and completely leveled him.  From my perspective, it almost looked like he was snapped in half backward.  I just can’t believe he got up from that play.  I was sure he was seriously injured.

This game did not seem like a preseason game at all.  Especially by the play of the defense.  The Pats will say otherwise, but I still think the Pats were seriously pissed by last year’s season finally against the Titans.  That was a brutally physical game in which Rodney Harrison was knocked out with an injury for the rest of the season by a cheap shot by one of the Titan’s receivers.  IMO, that one cheap shot cost the patriots another trip to the superbowl.  The AFC championship game was so close, just one play could have changed the whole complexion of that game, and I know a healthy Harrison would have turned the tables.  I think the Patriots wanted payback.  Keith Bullock didn’t help matters by saying he was gonna level Reche Caldwell in an interview before the game.  If you have followed the Pats for the past few years as I have, you know that the Patriots take any insult, however so minor, very very very personally.  They usually make their opponents pay for it.  Last night was no exception.

House red please

2 Comments

Recently, my wife and I were invited to a friends wine tasting party. It was fun because they made a game out of it. They had 10 bottles of red, 10 bottles of white covered to hide their identity and numbered. You received a card and had to match the wines listed on the card with the numbered bottle of wine. My wife and I love to go to nice restaurants and had sampled at least one of every type of wine listed on the cards, so we thought we had a really good chance of winning the game. Turns out, we only got one right, and that was to correctly identify the port. 🙂 I was sure I had 16-17 right on the card. So much for being a wine connoisseur. This experience taught me a valuable lesson. When going out to eat now, I’ll only buy the cheapest wine on the list. Kind or year doesn’t matter. I won’t know the difference.

Compensating Transaction Framework

5 Comments

Mark Little’s team has put together a nice annotation framework on top of the JBoss TS, Business Activity service. What?!? JBoss has a Business Activity service? Yup, we do. Have had it for a long while, accept nobody but Mark (did he even?) made any noise about it within the JBoss community. What is the Business Activity service? Mark does a better job in an article he wrote a few years ago, (his book is even better), so I won’t get into a lot of detail. To summarize in my own words, the Business Activity service looks very much like XA and traditional transactions, except they are really meant for long running conversations or activity. Traditional transactions are not good in that scenario because they hold onto resources too long. Particpants in BA look a lot like resources in XA. The register themselves with an activity. An activity is very similar to a transaction in that you begin it, and either cancel (rollback) or close (commit) the activity when you are finished. Participants can interact at closing with a 2 phase protocol, much like 2PC in regular XA. The difference is that the rules are much more lax. Participants can choose to leave the activity whenever they like as well as some other neat things. See Mark’s book or article for more details. Oh, and I forgot, this is a WS-* specification.

So back to the annotation framework. Its pretty cool. It allows you to tie in a compensatory action to an executed method. So, if the business activity is cancelled, the coordinator will automatically callback to this compensation. Here’s an example:

@Stateless
@SOAPBinding(style = SOAPBinding.Style.RPC)
@HandlerChain(file = "jaxws-ba-handler-server.xml")
public class HotelBAImpl implements HotelBA
{
	@WebMethod
	@BAService(BAServiceType.MODIFY)
	@BAAgreement(BAAgreementType.PARTICIPANT_COMPLETION)
	@BACompensatedBy(value="cancel",type = BACompensationType.PARAMETERS_MATCH)
	public Integer book(String user, String pass, Integer room)
	{
		// ... business logic
		return reservationNumber;
	}

	@WebMethod
	public void cancel(String user, String pass, Integer room)
	{
		// ... business logic
	}
}

So, in the example, if you invoke the book() method of the Hotel service, it will interact with the coordinator to register a compensation action. This action will be to invoke the cancel() method with the exact parameters that were passed into the book() method if the activity is aborted. Alternatively, you can map the book() method’s return value and parameters to the compensation action using the @BAResult and @BAParam.

{
	@WebMethod
	@BAService(BAServiceType.MODIFY)
	@BAAgreement(BAAgreementType.PARTICIPANT_COMPLETION)
	@BACompensatedBy(value="cancel",type = BACompensationType.CUSTOM)
        @BAResult("reservationNumber")
        public Integer book(@BAParam("user") String user, @BAParam("password") String pass, Integer room)
        {
           // ... business logic
          return reservationNumber;
        }

        @WebMethod
        public void cancel(@BAParam("reservationNumber") Integer reserverationNumber,
                                 @BAParam("user")String user, @BAParam("password") String pass)
        {
           // ... business logic
        }
}

There’s also a CompensationManager object that allows you to programatically put data into the activity that can be referenced by the @BAParam annotation:

{
        // injected field
        @CompensationManagement CompensationManager cm;

	@WebMethod
	@BAService(BAServiceType.MODIFY)
	@BAAgreement(BAAgreementType.PARTICIPANT_COMPLETION)
	@BACompensatedBy(value="cancel",type = BACompensationType.CUSTOM)
        public Integer book(String user, String pass, Integer room)
	{
		// ... business logic
               cm.put("reservationNumber", reservationNumber);

               return reservationNumber;
        }

        @WebMethod
        public void cancel(@BAParam("reservationNumber") Integer reserverationNumber)
        {
           // ... business logic
        }
}

There’s a few more ways to define a compensation. You can have the method compensated by another different EJB method, Web Service, or even a plain POJO. I won’t get into further detail. You’ll have to read the documentation and take a look at the demo app that comes with the distribution.

Client interface

The client interface is very simple and similar to UserTransaction:

public abstract class UserBusinessActivity
{
    public static final int ATOMIC_OUTCOME = 0;
    public static final int MIXED_OUTCOME = 1;

    /**
     * Start a new business activity with atomic outcome.
     * If one is already associated with this thread
     * then the WrongStateException will be thrown. Upon success, this
     * operation associates the newly created transaction with the current
     * thread.
     */
    public abstract void begin()
        throws WrongStateException, SystemException;

    /**
     * Start a new BA with atomic outcome and the specified timeout as
     * its lifetime.
     * If one is already associated with this thread then the
     * WrongStateException will be thrown.
     */
    public abstract void begin(final int timeout)
        throws WrongStateException, SystemException;

    /**
     * The BA is normally terminated by the close method. This signals to
     * all registered participants that the BA has ended and no compensation
     * is required.
     */
    public abstract void close()
        throws TransactionRolledBackException, UnknownTransactionException, SystemException;

    /**
     * If the BA must undo its work then the cancel method is used. Any
     * participants that can compensate are forced to do so.
     */
    public abstract void cancel()
        throws UnknownTransactionException, SystemException;

    /**
     * If participants have registered for the BusinessAgreementWithComplete
     * protocol then they will be expecting the application to inform them
     * when all work intended for them has been sent (and responded to). The
     * complete method is used for this purpose.
     */
    public abstract void complete()
        throws UnknownTransactionException, SystemException;

    public abstract String transactionIdentifier();
}

Here’s an example of using the activity service:

UserBusinessActivity businessActivity = UserBusinessActivityFactory.userBusinessActivity();
businessActivity.begin();
try {
   // do some work
   businessActivity.close();
} catch (Exception ex) {
   businessActivity.cancel();
}

There is of course some initialization to do. I’ll leave that to the documentation, but overall its a very simple API. What I like about this way of doing compensations is that the client is decoupled from the knowledge of whether something should be compensated for, and how it is compensated. The knowledge of this is encapsulated in the services the client interacts with. Services automatically register themselves for the appropriate callbacks. User code does not have to perform commits or rollbacks. Very similar in ease of use to what we’re used to with JCA combined with JTA transactions.

I really think this stuff would be even more useful in plain web applications, not just coordinated remote web services. In my previous blog, Andy Oliver commented how Hibernate application transactions with FlushMode NEVER isn’t always a great solution for long running web apps that interact with your browser. This new framework could provide a very simple mechanism for registering compensatory callbacks so that browser interactions with a database don’t have to be held in memory.

In my next blog on this subject, I want to dive into some ideas I have for improving this framework. Until then, have fun.

Websphere Children’s Edition

4 Comments

Its funny to see Novell re-hash a 10 month old press release that it is bundling Websphere Children’s Edition with Suse. My favorite quote from this newsclip is:

Users looking for more advanced features are steered towards paid WebSphere products, which offer more advanced features.

This is why we will never take Apache Geranium seriously.  As long as IBM is the major contributor to the project, they’ll never be interested in elevating Geranimo to the feature set of JBoss.   It will always be a hobbled platform.  This is why you should always read the fine print in vendor friendly open source projects.  If the project is dominated by a vendor which has a competing closed-source, expensive product, the project will never get anywhere.

Fake Steve unmasked!

Leave a comment

I was broken hearted today. The Fake Steve Jobs has been unmasked. I was kinda hoping it was the “real” Steve Jobs. I mean, what a great way it would have been for him to say whatever the hell he wanted without it harming himself or his company. You knew Fake Steve was biased towards Apple, so you wouldn’t have the rickardtards screaming astroturfing.

When I started this blog, I thought about naming it the “Fake Bill Burke” blog, so I could have full freedom to say whatever I wanted. But the problem would have been people thinking, “This is Bill Burke being his phony self, not somebody impersonating Bill Burke.” Also, my biases are so well documented, people would have known it was me. Finally, and most importantly, I have enough trouble getting people to read stuff from the “real” Bill Burke since most people don’t know who the hell Bill Burke is. In fact, if you do a Google Search, you’ll see that the “real”, real, Bill Burke is much more interesting than I am.

Guaranteed jBPM Failure Handling

2 Comments

jBPM 3.x allows you to define exception handlers in .jpdl. You can define exceptions you want to catch and either recover from the exception, or allow the execution to fail. These exception handlers are incomplete in functionality though. In my last blog, I talked about how asynchronous continuations give you the ability to have guaranteed transitions. If you dive into the asynchronous code though, you see that exception handlers are executed within the same transaction as the command service triggering the node execution. What does this mean? What are the consequences of this?

Let’s say that your action logic runs into an error condition and it needs to rollback any database changes it has made. Since the thread of execution is marked for rollback, you cannot make any changes to the execution context of the business process, for instance, like transitioning to a failure state. Any failure changes you make to the execution context would just be rolled back by the transaction. Another scenario is the guaranteed transitions I talked about in my last blog. On a rollback situation, what if you want to let your business process decide on whether the node execution should be tried again or not instead of the simple logic of the MDB’s retry count. We talked a bit about these problems on the jBPM forum. Let me summarize some solutions that were discussed.

Execute in a separate transaction

One approach is to solve the problem by invoking non-jbpm code in its own transaction. Your jbpm action could just delegate to an EJB or Spring bean that uses a REQUIRES_NEW semantic. If the invocation succeeds, populate the appropriate bpm variables and move on. If it fails, transition to a failure state or abort and retry the action.

I don’t think this is a good approach because you wouldn’t be able to use frameworks like Seam which make integrating business processes and business logic much easier. Seam uses annotations to biject (push data to and from) jbpm context data into your beans. Freeing you from writing a lot of jbpm specific code.

More importantly, I don’t think this is a solid solution. For instance, what if your non-jbpm code is successful and commits, but the machine crashes before the jbpm context commits? Then your system ends up in an inconsistent state and you are screwed.

Have a Failure State

A better way to solve this is to actually define a transition to a failure state in your process definition

<process-definition>
   <start-state>
     <transition to='business-state-1'/>
   </start-state>
   <state name='business-state-1' asynch='true'>
     ...
     <transition name="failure" to='failure-state-1'/>
   </state>
   <state name='failure-state-1' asynch='true'>
     ...
   </state>

...
</process-definition>

Your failure processing would be encapsulated within actions of the failure state instead of within exception handlers in the original business state. The failure state should be asynchronous because we want to get guaranteed processing of this state. There are two ways to ensure that either a) the business-state-1 state gets processed, or b) the failure state gets processed. I already discussed in a previous blog how to guarantee (a), but for (b) we needs some more thought.

Guarnateed failure handling: Dead Letter Queue Processing

One way to do guaranteed failure handling would be to take advantage of dead letter queues. Most MDB containers allow you to specify how many times you want a message redelivered. After the message redelivery count is reached and there still is failure, the container will reroute the message to a dead letter queue. This queue is a normal queue that you can listen on. Although not a standard JMS feature, I looked into it a little, and at least JBoss, ActiveMQ, and MQSeries have the notion of a DLQ.

So, to do jBPM failure handling, you could just register a new MDB to listen on the dead letter queue. Asynchronous continuations post instances of org.jbpm.job.ExecuteNodeJob. The MDB would check to see if the message contained an org.jbpm.job.ExecuteNodeJob, if it did, check the node for a “failure” transition. If one exists, then signal the process instance to traverse that “failure” transition.

@MessageDriven(activationConfig= {
      ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
      ActivationConfigProperty(propertyName="messageSelector", propertyValue="jobId IS NOT NULL"),
      ActivationConfigProperty(propertyName="destination", propertyValue="queue/DLQ")})
public class DLQFailureHandler implements MessageListener
{
    JbpmConfiguration jbpmConfiguration = null;
    @Resource(name="JbpmCfgResource") String jbpmCfgResource = null;

    @PostConstruct
    public void initJbpm() {
      jbpmConfiguration = JbpmConfiguration.getInstance(jbpmCfgResource);
    }

    public void onMessage(Message message) {
        long jobId = 0;
        try {
            jobId = message.getLongProperty("jobId");
        } catch (JMSException ignored) {
            // message selector confirms existence
        }

        JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
        try {
            JobSession jobSession = jbpmContext.getJobSession();
            Job job = jobSession.loadJob(jobId);
            if (!(job instanceof ExecuteNodeJob)) {
                // do some other failure handling
                jbpmContext.close();
                return;
            }
            ExecuteNodeJob executeNodeJob = (ExecuteNodeJob)job;
            if (executeNodeJob.getNode().hasLeavingTransition("failure")) {
                executeNodeJob.getProcessInstance().signal("failure");
                jobSession.deleteJob(job);
            }
            else {
                // push to a different DLQ?
            }
        } finally {
            jbpmContext.close();
        }
    }
}

To make sure we process dead jbpm jobs, we use a message selector configured at line 02. Lines 06-12 lookup and configure the jbpm context. Line 24-25 extracts the Job. If the Job is not an ExecuteNodeJob, you’ll want to add specific handling there or forward the message to another DLQ. Next in line 32 we check to see if the node has a “failure” transition. We transition and delete the job. If there is no “failure” transition, you might want to repost the message to a different DLQ that you create. If there is a failure in this processing, because of message delivery, we are still guaranteed to reprocess the failure logic.

The advantage of this approach is that it is totally seemless to your application: both in code and in your process diagram. You are guaranteed to either be in a successful or failure jbpm state. (At least with using the JBoss JMS inflow adapter but you should probably be ok in other implementations). The disadvantage of this approach is that you have no knowledge of the error condition and can’t report it to the “failure” state. Your failure logic will not know the cause of the failure. This isn’t always an issue because sometimes, specifically in a machine crash, you may not know why there is a failure.


Guaranteed failure handling: Transaction Synchronization

Another idea that came up in the forum discussion was to register a javax.transaction.Synchronization with the Transaction Manager. In afterCompletion(), do the transition to a failure state if there was a rollback. The advantage of such an approach over DLQ is that you can programmatically add the behavior in action code or write an action that performs the TM synchronization. Because of this, you can propagate any exception or failure reason to the failure state. I’m not going to get into details of this approach as I am not sure it will work, specifically:

  • You must set your redelivery count to 0. The synchronization has no way of knowing whether or not the message had been redelivered or whether or not you should transition the token to the failure state with jBPM code out-of-the-box. Since you don’t want the original JMS message redelivered after you have transitioned to the failure state, you need a retry count of zero.
  • JMS Providers may not be able to guarantee that a message isn’t redelivered. Since we require a redelivery count of zero, this is not an option.
  • Your machine could crash before transitioning to the failure state. Since we cannot redeliver the message, the node will never transition to the failure state. You may say, “well, can’t the same thing happen with the DLQ option?”. With the JBoss Inflow adapter, no. The JBoss adapter performs the DLQ check within the same transaction as the delivered method. Since both the sending to the DLQ and acknowledgement of the message are within the same transaction, you are guaranteed of one or the other succeeding.
  • Probably the most important thing is that Synchronization.afterCompletion() is not guaranteed to be executed on TX recover, after a machine crash.

So, the winner is DLQ! Of course I may have missed something. This approach would be better if we could work out the issues.

Side Effect: Redelivery handling

In my previous blog on Guaranteed Execution in jBPM, I discussed at the end how jBPM actions have know current way of knowing whether or not they have been retried by a new transaction. An indirect consequence of the DLQ approach to failure handling is that we now have some ability to recognize and keep track of redeliveries.

<process-definition>
   <start-state>
     <transition to='guarantee'/>
   </start-state>
   <state name='business-state-1' asynch='true'>
     ...
     <transition name="failure" to='failure-state-1'/>
   </state>
   <decision name='failure-state-1' asynch='true'>
     <transition name="recover" to='recovery-state-1'>
        <condition expression="retryCount >=3"/>
     </transition>
     <transition name="retry" to='business-state-1'>
        <condition expression="retryCount < 3"/>
     </transition>

   </state>

...
</process-definition>

Since failures result in a transition to a failure state we can keep increment and store redelivery counts within the token. We can programmatically decide wheter or not we are allowed to retry the message.

Conclusion

So that’s how you can have guaranteed failure handling. I do have a disclaimer though. I’m too lazy to actually try out these ideas. When I do I’ll get back to you in a follow up blog. Please try it out yourself and provide feedback on the jbpm forum topic. We’re still working out the issues here and your thoughts would be most appreciated.

New preformatted style

2 Comments

This is for all you WordPress blog users.  The preformatted text style of my blog theme was awful.  It was hard to read so I started cycling through the WordPress themes to find a better one.  The “Freshy” them had the best style, but I don’t like any other style point of it.  I didn’t know CSS, but was able to steal the preformatted text and add it it to this blog’s CSS template.

pre,code {
display:block;
font:1em 'Courier New', Courier, Fixed, monospace;
font-size:100%;
color:#000;
background:#fff url('/wp-content/themes/pub/freshy/images/preback.jpg') no-repeat left top;
overflow:auto;
text-align:left;
border:1px solid #99cc66;
line-height:17px;
margin:1em 0;
padding:0 20px 0 30px;
}

Well there it is.  This was my first taste of touching a CSS template.  Hey, I actually learned something!

MarcF interview

1 Comment

How’s Marc Fleury doing?  Matt Asay gave a pretty good interview with Marc.

Older Entries Newer Entries