Rolling back a transaction

So far we have seen transaction success or failure determined naturally—that is, by whether an exchange was successfully processed, or if an exception was thrown during its processing. This recipe will provide you with a number of additional options around controlling transaction rollback.

Getting ready

The Java code for this recipe is located in the org.camelcookbook.transactions.rollback package. The Spring XML files are located under src/main/resources/META-INF/spring and prefixed with rollback.

How to do it...

You can use the rollback DSL statement to throw an exception with an optional message.

In the XML DSL, we use the following code:

<from uri="direct:transacted"/>
<transacted/>
<setHeader headerName="message">
  <simple>${body}</simple>
</setHeader>
<to uri="sql:insert into audit_log (message) values (:#message)"/>
<choice>
  <when>
    <simple>${body} contains 'explode'</simple>
    <rollback message="Message contained word 'explode'"/>
  </when>
</choice>

In the Java DSL, the same thing is expressed as follows:

from("direct:transacted")
  .transacted()
  .setHeader("message", body())
  .to("sql:insert into audit_log (message) values (:#message)")
  .choice()
    .when(simple("${body} contains 'explode'"))
    .rollback("Message contained word 'explode'")
  .endChoice();

How it works...

When an exchange triggers a rollback, a org.apache.camel.RollbackExchangeException object is thrown with the message specified. This will cause the transaction error handler to rollback any transactions currently in progress for this exchange. The exception itself will be wrapped in an org.apache.camel.CamelExecutionException instance before being returned to the consuming endpoint.

Being a regular exception, a rollback may be caught by an onException block, such as:

.onException(RollbackExchangeException.class)
  .log("Caught rollback signal")
.end()

There's more...

You can trigger rollback behavior without an exception being thrown through the use of the markRollbackOnly statement. This will cause the exchange to stop being processed immediately, and any transactions currently in progress to be rolled back. Camel will consider the exchange's processing to have been successfully completed.

In the XML DSL, markRollbackOnly is an attribute of the rollback element:

<choice>
  <when>
    <simple>${body} contains 'explode'</simple>
    <rollback markRollbackOnly="true"/>
  </when>
</choice>

In the Java DSL, it is a DSL statement in its own right:

.choice()
  .when(simple("${body} contains 'explode'"))
    .markRollbackOnly()
.endChoice()

If you are nesting transactions, it is possible to roll back the current, or deepest, transaction only by using markRollbackOnlyLast. In the following example, a message that contains the word "explode" will cause the inner transaction, tx2, to be rolled back. No further processing will take place in route2, and so the exchange will not reach the mock:out2 endpoint. The exchange will, however, continue to be processed by route1, and will therefore be sent to the mock:out1 endpoint. The transaction tx1 will be committed successfully:

<route id="route1">
  <from uri="direct:route1"/>
  <setHeader headerName="message">
    <simple>${body}</simple>
  </setHeader>
  <policy ref="PROPAGATION_REQUIRES_NEW" id="tx1">
    <to uri="sql:insert into messages (message) values(:#message)"/>
    <to uri="direct:route2"/>
    <to uri="mock:out1"/>
  </policy>
</route>

<route id="route2">
  <from uri="direct:route2"/>
  <policy ref="PROPAGATION_REQUIRES_NEW-2" id="tx2">
    <to uri="sql:insert into audit_log (message) values(:#message)"/>
    <choice>
      <when>
        <simple>${body} contains 'explode'</simple>
        <rollback markRollbackOnlyLast="true"/>
      </when>
    </choice>
    <to uri="mock:out2"/>
  </policy>
</route>

In the Java DSL, the equivalent logic is expressed as:

from("direct:route1").id("route1")
  .setHeader("message", simple("${body}"))
  .policy("PROPAGATION_REQUIRES_NEW").id("tx1")
    .to("sql:insert into messages (message) values (:#message)")
    .to("direct:route2")
    .to("mock:out1")
  .end();

from("direct:route2").id("route2")
  .policy("PROPAGATION_REQUIRES_NEW-2").id("tx2")
    .to("sql:insert into audit_log (message) values (:#message)")
    .choice()
      .when(simple("${body} contains 'explode'"))
        .markRollbackOnlyLast()
    .endChoice()
    .to("mock:out2")
  .end();
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.255.36