Git Product home page Git Product logo

quarkus-pooled-jms's Introduction

Quarkus Messaginghub Pooled JMS Extension

All Contributors

Build License Central

This extension provides JMS Connection pool for messaging applications that provides pooling for JMS Connections, Sessions and MessageProducers. Also it can be integrated with transaction manager to support XA JTA which is provided by Quarkus Narayana JTA. Add the following dependency in your pom.xml to get started,

<dependency>
    <groupId>io.quarkiverse.messaginghub</groupId>
    <artifactId>quarkus-pooled-jms</artifactId>
</dependency>

For more information and quickstart, you can check the complete documentation.

Contributors โœจ

Thanks goes to these wonderful people (emoji key):


Amos Feng

๐Ÿ’ป ๐Ÿšง

This project follows the all-contributors specification. Contributions of any kind welcome!

quarkus-pooled-jms's People

Contributors

actions-user avatar allcontributors[bot] avatar dependabot[bot] avatar gastaldi avatar gemmellr avatar zhfeng avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

quarkus-pooled-jms's Issues

Dependency quarkus-narayana-jta does not seem to be optional

Describe the bug

When using quarkus-artemis-jms in conjunction with quarkus-pooled-jms and without xa-supprt, e.g. through the following application.yml:

quarkus:
  artemis:
    url: tcp://${ARTEMIS_HOST:localhost}:${ARTEMIS_PORT:61616}
    username: ${ARTEMIS_USERNAME:artemis}
    password: ${ARTEMIS_PASSWORD:artemis}
  pooled-jms:
    pooling:
      enabled: true
    max-connections: 2

then quarkus-pooled-jms fails on mvn package with:

...
[ERROR] Failed to execute goal io.quarkus:quarkus-maven-plugin:2.13.3.Final:build (default) on project sender: Failed to build quarkus application: Failed to load steps from class io.quarkiverse.messaginghub.pooled.jms.deployment.PooledJmsProcessor: io/quarkus/narayana/jta/runtime/TransactionManagerConfiguration: io.quarkus.narayana.jta.runtime.TransactionManagerConfiguration -> [Help 1]
...

Expected behaviour

Application compiles, and ConnectionFactory is not XA-capable.

Actual behaviour

Compilation fails.

Technica details

quarkus version: 2.13.3.FINAL, 2.14.0.FINAL
quarkus-artemis-jms version: 1.3.0, 2.0.0, 2.0.1 (have not verified others)
quakrus-pooled-jmsversion: 1.0.3 (have not verified others)
javac version: 17.0.4

Reproducer

Additional Information

If we uncomment sender/pom.xml, Lines 35 to 38, the application compiles as expected.

Prepare for Quarkus 3.0.0

In the advent of the Quarkus 3.0.0 release, we should prepare this extension.

We depend on quarkus-artemis-jms, therefore we need builds of this extension in order to test compatibility.

Current release of quarkus-artemis-jms:Version

deployment module always tries to register Artemis JMS CF for reflection

When trying to use quarkus-pooled-jms with a client other than the Artemis JMS client, a warning is emitted during native builds due to failure to register the ActiveMQConnectionFactory class for reflection:

Warning: Could not resolve org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory for reflection configuration. Reason: java.lang.ClassNotFoundException: org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.

Presumably this is because it always tries to register it, without checking to see if it is present:

reflectiveClasses.produce(
ReflectiveClassBuildItem.builder("org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory")
.methods(true).fields(false).build());

It clearly shouldn't if it isn't present. It isnt clear to me that that it should be doing so even if it is present.

Consumers change hosts over time.

Hi @zhfeng

We have a problem with the load balancing consumers to a jboss cluster. They don't stay connected to the same server over time.

Let's contextualize by our infrastructure :

We have a HornetQ jms broker hosted by two jboss eap6 servers. With artemis client, We connect to our cluster by this url (tcp://jbosshost01:5049,tcp://jbosshost01:5049)?protocolManagerFactoryStr=org.apache.activemq.artemis.core.protocol.hornetq.client.HornetQClientProtocolManagerFactory. All servers have a queue in our cluster, so here two queues. For the load balancing needs or move messages from jbosshost01 to jbosshost01 or reverse, some queues exist between servers to move messages if needed.

The cluster look like below in the best situation. Two servers with two consumer on each. It should be more in production.


                                   some producers
    
                                           โ”‚
                         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                         โ”‚                                      โ”‚
                         โ”‚                                      โ”‚
    business.queue.name  โ”‚                                      โ”‚   business.queue.name
                         โ”‚                                      โ”‚
                         โ–ผ                                      โ–ผ
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   load balance queue 1   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚           โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ  โ”‚           โ”‚
                    โ”‚  host1    โ”‚                          โ”‚  host2    โ”‚
                    โ”‚           โ”‚   load balance queue 2   โ”‚           โ”‚
                    โ”‚           โ”‚  โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โ”‚           โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜                          โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                          โ”‚                                     โ”‚
                          โ”‚                                     โ”‚
    business.queue.name   โ”‚                                     โ”‚  business.queue.name
                          โ”‚                                     โ”‚
                          โ–ผ                                     โ–ผ
                     consumer a                             consumer b
                     consumer c                             consumer d

Consumer balancing is not stable over a long period of time. They change servers. For example, consider 2 connexion and 4 consumer, the consumer balancing number could be like following :

        host 1     host 2
          1          3
          0          4
          3          1
          4          0

Sending messages or not, it's the same.

This behavior on the client side is handled by the default class RoundRobinConnectionLoadBalancingPolicy in Artemis Client.
how to keep a consumer connected to a server, no matter how many times a connection and a session are created on the cluster ?

An example of the code that we use inside our consumer.

   // this following consumeMessages() method is called by 4 thread in parallel which are run by a scheduler quarkus

	@Transactional(Transactional.TxType.NEVER)
    private void consumeMessages() throws JMSException {
        log.debug("start session consuming activity");
        try (Connection connection = factory.createConnection();
                Session session = connection.createSession(Session.SESSION_TRANSACTED);
                MessageConsumer consumer = session.createConsumer(queue)) {
            connection.start();
            var instant = LocalTime.now();
            while (isStillInActivity(instant)) {
                var message = consumer.receive(MESSAGE_RECEPTION_TIMEOUT.toMillis());
                if (message != null) {
                    log.debug("session thread treat message");
                    boolean ok = false;
					try {
						listener.onMessage(message);
						session.commit();
						log.debug("### session commit");
						ok = true;
					} finally {
						if (!ok) {
							session.rollback();
							log.debug("### session rollback");
						}
					}
                } else {
                    log.debug("session thread remains idle");
                }
            }
            log.debug("end session activity successfully");
        }
    }

    private boolean isStillInActivity(LocalTime instant) {
        LocalTime timeout = instant.plus(sessionTTL);
        return LocalTime.now().isBefore(timeout) && !shutdown.get();
    }

Thanks !

Bind jms transaction (not XA) on the transaction manager of quarkus

Hi all,

We would like the integration with the transaction manager to be extended to support also non XA transactions.
We are using Quarkus as the foundation for our microservices in OpenShift, and as a result, we want to stay stateless; so we do not intend to activate a XA compliant transaction manager inside Quarkus.
Yet, we would like to manage the transaction on our JMS resource manager through JTA Transactional annotation, as opposed to use the JMS api to manage the transaction boundary on the JMS broker.
Specifically, we would like the testRollback() to pass in https://github.com/quarkiverse/quarkus-pooled-jms/blob/main/integration-tests/src/test/java/io/quarkiverse/messaginghub/pooled/jms/it/PooledJmsResourceTest.java#L31-L42 even if I comment out
property quarkus.pooled-jms.xa.enabled=true in https://github.com/quarkiverse/quarkus-pooled-jms/blob/main/integration-tests/src/main/resources/application.properties#L2-L3

At the implementation level, we see that PooledXAConnection has support for a provided transactionManager.
We would like JmsPoolConnectionFactory to support using a transactionmanager as well, so that we can control the transaction on the broker, from the Quarkus transaction manager.

Thanks.

native builds fail unless narayana-jta is also present

The quarkus-pooled-jms deployment module has an optional dependency on quarkus-narayana-jta-deployment (with the XA support for the pooling being disabled by default), however it appears the extension really requires some bits from it be present. A native application build using quarkus-pooled-jms, not doing any XA at all, fails without it due to class org.jboss.tm.XAResourceRecoveryRegistry not being found:

Caused by: org.graalvm.compiler.java.BytecodeParser$BytecodeParserError: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved type during parsing: org.jboss.tm.XAResourceRecoveryRegistry. This error is reported at image build time because class io.quarkiverse.messaginghub.pooled.jms.PooledJmsWrapper is registered for linking at image build time by command line

(For more complete stack, see later)

This was noticed simple adding the quarkus-pooled-jms 2.0.0 dependency to an application using quarkus-qpid-jms 2.0.0, building with Mandrel 22.3.2.0 . Not even actually using the pool yet. Adding the dependency on quarkus-narayana-jta-deployment to the application itself, even though it wasnt doing any XA, was required to get the build to work with quarkus-pooled-jms in place.

More complete stacks:

Fatal error: com.oracle.graal.pointsto.util.AnalysisError$ParsingError: Error encountered while parsing io.quarkiverse.messaginghub.pooled.jms.PooledJmsWrapper.wrapConnectionFactory(jakarta.jms.ConnectionFactory) 
Parsing context:
   at io.quarkiverse.messaginghub.pooled.jms.PooledJmsWrapper.wrapConnectionFactory(PooledJmsWrapper.java:24)
   at io.quarkiverse.messaginghub.pooled.jms.PooledJmsRecorder.lambda$getWrapper$0(PooledJmsRecorder.java:20)
   at io.quarkiverse.messaginghub.pooled.jms.PooledJmsRecorder$$Lambda$965/0x00000007c132e8a8.apply(Unknown Source)
   at io.smallrye.context.SmallRyeManagedExecutor_37cd00d79f6817c9ac6f4041646d6c5b8c1d4c69_Synthetic_Bean.createSynthetic(Unknown Source)
   at io.smallrye.context.SmallRyeManagedExecutor_37cd00d79f6817c9ac6f4041646d6c5b8c1d4c69_Synthetic_Bean.doCreate(Unknown Source)
   at io.smallrye.context.SmallRyeManagedExecutor_37cd00d79f6817c9ac6f4041646d6c5b8c1d4c69_Synthetic_Bean.create(Unknown Source)
   at io.smallrye.context.SmallRyeManagedExecutor_37cd00d79f6817c9ac6f4041646d6c5b8c1d4c69_Synthetic_Bean.create(Unknown Source)
   at io.quarkus.arc.impl.RequestContext.getIfActive(RequestContext.java:74)
   at io.quarkus.arc.impl.RequestContext.get(RequestContext.java:82)
   at org.acme.jms.PriceProducer_Observer_onStart_66a261b0dd2a8c542d0c570163f0a57eedc14ef7.notify(Unknown Source)
   at io.quarkus.arc.impl.EventImpl$Notifier.notifyObservers(EventImpl.java:346)
   at io.quarkus.arc.impl.EventImpl$Notifier.notify(EventImpl.java:328)
   at io.quarkus.arc.impl.EventImpl$Notifier.notify(EventImpl.java:263)
   at io.quarkus.arc.impl.ArcContainerImpl.shutdown(ArcContainerImpl.java:397)
   at io.quarkus.arc.Arc.shutdown(Arc.java:72)
   at io.quarkus.arc.runtime.ArcRecorder$1.run(ArcRecorder.java:53)
   at java.lang.Shutdown.runHooks(Shutdown.java:130)
   at java.lang.Shutdown.shutdown(Shutdown.java:185)
   at com.oracle.svm.core.jdk.RuntimeSupport.shutdown(RuntimeSupport.java:154)

	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.AnalysisError.parsingError(AnalysisError.java:153)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:104)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.ensureFlowsGraphCreated(MethodTypeFlow.java:83)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.getOrCreateMethodFlowsGraph(MethodTypeFlow.java:65)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.DefaultSpecialInvokeTypeFlow.onObservedUpdate(DefaultSpecialInvokeTypeFlow.java:61)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.TypeFlow.update(TypeFlow.java:562)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.PointsToAnalysis$1.run(PointsToAnalysis.java:488)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:193)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:177)
	at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1395)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Caused by: org.graalvm.compiler.java.BytecodeParser$BytecodeParserError: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved type during parsing: org.jboss.tm.XAResourceRecoveryRegistry. This error is reported at image build time because class io.quarkiverse.messaginghub.pooled.jms.PooledJmsWrapper is registered for linking at image build time by command line
	at parsing io.quarkiverse.messaginghub.pooled.jms.PooledJmsWrapper.getXAConnectionFactory(PooledJmsWrapper.java:44)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.throwParserError(BytecodeParser.java:2518)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.throwParserError(SharedGraphBuilderPhase.java:110)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3393)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.handleBytecodeBlock(BytecodeParser.java:3345)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.processBlock(BytecodeParser.java:3190)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.build(BytecodeParser.java:1138)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.buildRootMethod(BytecodeParser.java:1030)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.GraphBuilderPhase$Instance.run(GraphBuilderPhase.java:97)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase.run(SharedGraphBuilderPhase.java:84)
	at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.run(Phase.java:49)
	at jdk.internal.vm.compiler/org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:446)
	at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.apply(Phase.java:42)
	at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.apply(Phase.java:38)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.AnalysisParsedGraph.parseBytecode(AnalysisParsedGraph.java:135)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.ensureGraphParsed(AnalysisMethod.java:685)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysisGraphDecoder.lookupEncodedGraph(InlineBeforeAnalysis.java:180)
	at jdk.internal.vm.compiler/org.graalvm.compiler.replacements.PEGraphDecoder.doInline(PEGraphDecoder.java:1162)
	at jdk.internal.vm.compiler/org.graalvm.compiler.replacements.PEGraphDecoder.tryInline(PEGraphDecoder.java:1145)
	at jdk.internal.vm.compiler/org.graalvm.compiler.replacements.PEGraphDecoder.trySimplifyInvoke(PEGraphDecoder.java:1003)
	at jdk.internal.vm.compiler/org.graalvm.compiler.replacements.PEGraphDecoder.handleInvoke(PEGraphDecoder.java:957)
	at jdk.internal.vm.compiler/org.graalvm.compiler.nodes.GraphDecoder.processNextNode(GraphDecoder.java:817)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysisGraphDecoder.processNextNode(InlineBeforeAnalysis.java:240)
	at jdk.internal.vm.compiler/org.graalvm.compiler.nodes.GraphDecoder.decode(GraphDecoder.java:548)
	at jdk.internal.vm.compiler/org.graalvm.compiler.replacements.PEGraphDecoder.decode(PEGraphDecoder.java:833)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.phases.InlineBeforeAnalysis.decodeGraph(InlineBeforeAnalysis.java:98)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.parse(MethodTypeFlowBuilder.java:179)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.apply(MethodTypeFlowBuilder.java:349)
	at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:93)
	... 13 more
Caused by: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved type during parsing: org.jboss.tm.XAResourceRecoveryRegistry. This error is reported at image build time because class io.quarkiverse.messaginghub.pooled.jms.PooledJmsWrapper is registered for linking at image build time by command line
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.reportUnresolvedElement(SharedGraphBuilderPhase.java:333)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.handleUnresolvedType(SharedGraphBuilderPhase.java:288)
	at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.handleUnresolvedLoadConstant(SharedGraphBuilderPhase.java:259)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.genLoadConstant(BytecodeParser.java:3945)
	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.processBytecode(BytecodeParser.java:5124)
------------------------------------------------------------------------------------------------------------------------	at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3385)
	... 38 more

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.