Uploaded image for project: 'Camel'
  1. Camel
  2. CAMEL-21216

Apache Camel LRA does not work with Oracle MicroTX LRA coordinator

Attach filesAttach ScreenshotVotersWatch issueWatchersCreate sub-taskLinkCloneUpdate Comment AuthorReplace String in CommentUpdate Comment VisibilityDelete Comments
    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Minor
    • Resolution: Fixed
    • 4.7.0
    • 4.8.1, 4.9.0
    • camel-lra
    • None
    • Unknown

    Description

      Hi Team,

      we are using the Apache Camel LRA components within Java Springboot projects to implement saga services.

      Till now, we are using Narayana as an LRA-Coordinator. Now we want to switch to Oracl MicroTX
      (https://docs.oracle.com/en/database/oracle/transaction-manager-for-microservices/24.2/tmmdg/lra-transaction-protocol.html).

      After configuring Oracle MircoTX instead of Narayana, we are facing two problems within the
      Apache Camel LRA component code.

      1) While joining an LRA Transaction, the payload sent by Apache Camel is URL encoded
      2) The Query parameter sent by Oracle LRA coordinator are url encoded, but will not be decoded by Apache Camal LRA (see also: CAMEL-21197)

      I will set up a branch with my suggested code changes and link this afterwards to this jira bug.
      The code changes are completely backwards compatible with Narayana (already tested).

      1) Joining an LRA Transaction

      The class 'LRAClient' is using 'LRAUrlBuilder' inside Method 'join'. All parts of the http put body are url encoded.
      Within Oracle LRA Coordinator log i can see the incomming request from Apache Camel:

       

      <https://k5-mmeeasysaga.qa-servicebuilder-dev.svc.cluster.local/camel/compensate?Camel-Saga-Complete=direct%3A%2F%2Fsaga1_sagaService_complete>; rel=compensate,<https://k5-mmeeasysaga.qa-servicebuilder-dev.svc.cluster.local/camel/complete?Camel-Saga-Complete=direct%3A%2F%2Fsaga1_sagaService_complete>; rel=complete

      This url encoded query param 'Camel-Saga-Complete=direct%3A%2F%2Fsaga1_sagaService_complete' will be encoded again on Oracle LRA Coordinator side.
      This is causing the error message within Apache Camel LRA:

       

      o.a.c.RuntimeCamelException: Cannot join LRA  at o.a.c.s.l.LRAClient.lambda$join$2(LRAClient.java:138)  ... 10 common frames omitted Wrapped by: j.u.c.CompletionException: org.apache.camel.RuntimeCamelException: Cannot join LRA  at j.u.c.CompletableFuture.encodeThrowable(Unknown Source)  at j.u.c.CompletableFuture.completeThrowable(Unknown Source)  at j.u.c.CompletableFuture$UniApply.tryFire(Unknown Source)  at j.u.c.CompletableFuture.postComplete(Unknown Source)  at j.u.c.CompletableFuture.postFire(Unknown Source)  at j.u.c.CompletableFuture$UniWhenComplete.tryFire(Unknown Source)  at j.u.c.CompletableFuture$Completion.exec(Unknown Source)  at j.u.c.ForkJoinTask.doExec(Unknown Source)  at j.u.c.ForkJoinPool$WorkQueue.topLevelExec(Unknown Source)  at j.u.c.ForkJoinPool.scan(Unknown Source)  at j.u.c.ForkJoinPool.runWorker(Unknown Source)  at j.u.c.ForkJoinWorkerThread.run(Unknown Source)

       

      When logging the result http code and body

       

      LOG.error("error while joining LRA: {} / {}", response.statusCode(), response.body());

      i am getting this:

      error while joining LRA: 400 / error: URL is double encoded

      The problem can be solved by not url encoding the given urls within the joinLRA payload.
       
      org.apache.camel.service.lra.LRAUrlBuilder -> query:
       
      This code should not be executed:

       

      key = URLEncoder.encode(toNonnullString(key), StandardCharsets.UTF_8.name());  value = URLEncoder.encode(toNonnullString(value), StandardCharsets.UTF_8.name()); 
       

       
      2) Decode given query parameter from Oracle LRA-Coordinator call

      After solving 1), i am getting a new exception:

      
      j.l.IllegalArgumentException: URI direct%3A%2F%2Fsaga1_sagaService_complete is not allowed  at o.a.c.s.l.LRASagaRoutes.verifyRequest(LRASagaRoutes.java:107)  at o.a.c.s.p.DelegateSyncProcessor.process(DelegateSyncProcessor.java:65)  at o.a.c.p.e.RedeliveryErrorHandler$SimpleTask.handleFirst(RedeliveryErrorHandler.java:440)  at o.a.c.p.e.RedeliveryErrorHandler$SimpleTask.run(RedeliveryErrorHandler.java:416)  at o.a.c.i.e.DefaultReactiveExecutor$Worker.doRun(DefaultReactiveExecutor.java:199)  at o.a.c.i.e.DefaultReactiveExecutor$Worker.executeReactiveWork(DefaultReactiveExecutor.java:189)  at o.a.c.i.e.DefaultReactiveExecutor$Worker.tryExecuteReactiveWork(DefaultReactiveExecutor.java:166)  at o.a.c.i.e.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:148)  at o.a.c.i.e.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:59)  at o.a.c.p.Pipeline.process(Pipeline.java:163)  at o.a.c.i.e.CamelInternalProcessor.processNonTransacted(CamelInternalProcessor.java:346)  at o.a.c.i.e.CamelInternalProcessor.process(CamelInternalProcessor.java:322)  at o.a.c.i.e.DefaultAsyncProcessorAwaitManager.process(DefaultAsyncProcessorAwaitManager.java:82)  at o.a.c.s.AsyncProcessorSupport.process(AsyncProcessorSupport.java:32)  at o.a.c.h.c.CamelServlet.doExecute(CamelServlet.java:313)  at o.a.c.h.c.CamelServlet.doService(CamelServlet.java:235)  at o.a.c.h.c.CamelServlet.handleService(CamelServlet.java:111)  at o.a.c.h.c.CamelServlet.service(CamelServlet.java:97)  at j.s.h.HttpServlet.service(HttpServlet.java:614)  ... 5 frames excluded  at k.s.s.s.c.SagaContextFilter.doFilterInternal(SagaContextFilter.java:52)  ... 4 frames excluded  at o.s.s.w.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231)  at o.s.s.w.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479)  at o.s.s.w.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340)  at o.s.s.w.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82)  ... 2 frames excluded  at o.s.s.w.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240)  ... 110 frames truncated

       

      After finalizing the saga, the Oracle LRA-Coordinator is calling the 'onComplete' for all participants and the service.

       

       PUT /camel/complete?Camel-Saga-Compensate=direct%3A%2F%2Fsaga1_participant1_compensate&Camel-Saga-Complete=direct%3A%2F%2Fsaga1_participant1_complete

      Within o.a.c.s.l.LRASagaRoutes.verifyRequest(LRASagaRoutes.java:107) the extracted query param 'Camel-Saga-Compensate' is still url encoded:

       direct%3A%2F%2Fsaga1_sagaService_complete

      Therefore the check within LRASagaRoutes.verifyRequest fails, because the valid (indexed) uri is

       direct://saga1_sagaService_complete

      The problem can completely solved by CAMEL-21197. In the meantime in will provide a suggestion for an workaround.

      best regards
      Dirk

      Attachments

        Issue Links

        Activity

          This comment will be Viewable by All Users Viewable by All Users
          Cancel

          People

            zhfeng Zheng Feng
            dfiedler Dirk Fiedler
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Slack

                Issue deployment