Implementing JMS using jBPM and embedded ActiveMQ in EAP

In this post, I will be covering JMS messaging using the embedded ActiveMQ broker within EAP and a custom jBPM WorkItemHandler.

For this setup, I used the following:

  • EAP 7.0 (one instance)
  • jBPM 6.5.x (source)
    The wars can be built from the following projects.  You should rename them to kie-wb.war and kie-server.war, as these are included in context paths used on the server.

1.  Deploy the Kie Workbench & Kie Server

Assuming a proper installation and setup of EAP 7.0 exists and you have the kie workbench and kie server wars ready to go in the deployment directory, we can start the server like so:

./standalone.sh --server-config=standalone-full.xml -Dorg.kie.server.id=jms-kieserver -Dorg.kie.server.location=http://localhost:8080/kie-server/services/rest/server -Dorg.kie.server.controller=http://localhost:8080/kie-wb/rest/controller -Dorg.kie.server.controller.user=anna -Dorg.kie.server.controller.pwd=anna

To use the JMS subsystem that is predefined in EAP, you should use the standalone-full configuration.

If you need help deploying the kie workbench and kie server on a single server instance, my team mate Maciej has written a very easy-to-follow guide.

2.  Create a Custom WorkItemHandler Project

A WorkItemHandler is an object we can use to execute or abort a work item.   For the purpose of this demo, the “work item” we will execute should send a JMS message to the Kie Server to complete a process.

Create a new Maven project using your choice of tooling.

You can access the sample project here.  The WIH contains the following:

package org.repro.wih;

import java.util.Collections;
import java.util.UUID;

import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.kie.api.runtime.process.WorkItem;
import org.kie.api.runtime.process.WorkItemHandler;
import org.kie.api.runtime.process.WorkItemManager;
import org.kie.server.api.commands.CommandScript;
import org.kie.server.api.commands.DescriptorCommand;
import org.kie.server.api.jms.JMSConstants;
import org.kie.server.api.marshalling.Marshaller;
import org.kie.server.api.marshalling.MarshallerFactory;
import org.kie.server.api.marshalling.MarshallingFormat;
import org.kie.server.api.model.KieServerCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestJMSWorkItemHandler implements WorkItemHandler {

	private static final Logger logger = LoggerFactory.getLogger(TestJMSWorkItemHandler.class);

	private static int numReqMsgs = 10000;
	private static WorkItem workItem = null;

	// connection factory
	private static String XAConnectionFactory = "java:/JmsXA";

	// kie server user
	private static String servUser = "admin";
	private static String servPass = "admin";

	// workbench user
	private static String wbUser = "test";
	private static String wbPass = "test";

	// session creation params
	private static boolean tx = true;
	private int ack = Session.SESSION_TRANSACTED;

	public void abortWorkItem(WorkItem arg0, WorkItemManager arg1) {
		// do nothing
	}

	public void executeWorkItem(WorkItem item, WorkItemManager manager) {
		workItem = item;

		logger.info("**** Inside TestJMSWorkItemHandler, suspending.... ****");

		try {
			// queue setup
			InitialContext initialContext = new InitialContext();
			Queue requestQueue = (Queue) initialContext.lookup("queue/KIE.SERVER.REQUEST");

			QueueConnectionFactory connectionFactory = (QueueConnectionFactory) initialContext
					.lookup(XAConnectionFactory);
			logger.info("WIH is using connectionFactory {}", connectionFactory.getClass());

			QueueConnection connection = (QueueConnection) connectionFactory.createConnection(servUser, servPass);

			// if we use the global pool, connection factory will take care of
			// first parameter
			Session session = connection.createQueueSession(tx, ack);
			logger.debug("WIH session tx, ack are {}", session.getTransacted(), session.getAcknowledgeMode());

			MessageProducer producer = session.createProducer(requestQueue);

			// process-relevant information needed to marshall the service
			// commands
			String containerId = "org.kie.testing:new-jms-test:1.0.0-SNAPSHOT";
			Number processInstanceId = workItem.getProcessInstanceId();
			Number workItemId = workItem.getId();

			// marshall commands to be used
			String signalsCommand = getCommandString(containerId, processInstanceId, workItemId, "getAvailableSignals");
			String completeCommand = getCommandString(containerId, processInstanceId, workItemId, "completeWorkItem");

			// jms message setup for getAvailableSignals commands
			TextMessage message = null;
			message = prepMessage(session, message, signalsCommand, containerId);

			int i = 0;
			for (i = 0; i < numReqMsgs; i++) {
				message.setJMSCorrelationID(UUID.randomUUID().toString());
				producer.send(message);
			}

			if (i == numReqMsgs) {
				logger.info("WIH has completed sending {} getAvailableSignals commands:", numReqMsgs);
			}

			// jms message setup for completeWorkItem command
			message = prepMessage(session, message, completeCommand, containerId);
			producer.send(message);
			logger.info("WIH has completed sending {} completeWorkItem command.");

			producer.close();
			session.close();
			connection.close();

			// TODO Auto-generated catch block
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NamingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static WorkItem getWorkItem() {
		return workItem;
	}

	private static TextMessage prepMessage(Session session, TextMessage message, String commandString,
			String containerId) throws JMSException {
		message = session.createTextMessage(commandString);
		message.setJMSCorrelationID(UUID.randomUUID().toString());
		message.setStringProperty(JMSConstants.USER_PROPERTY_NAME, wbUser);
		message.setStringProperty(JMSConstants.PASSWRD_PROPERTY_NAME, wbPass);
		message.setStringProperty(JMSConstants.TARGET_CAPABILITY_PROPERTY_NAME, "BPM");
		message.setStringProperty(JMSConstants.CONTAINER_ID_PROPERTY_NAME, containerId);
		message.setIntProperty(JMSConstants.SERIALIZATION_FORMAT_PROPERTY_NAME, MarshallingFormat.JAXB.getId());
		message.setIntProperty(JMSConstants.INTERACTION_PATTERN_PROPERTY_NAME, JMSConstants.REQUEST_REPLY_PATTERN);
		return message;
	}

	private static String getCommandString(String containerId, Number processInstanceId, Number workItemId,
			String processService) {
		Marshaller marshaller = MarshallerFactory.getMarshaller(Collections.<Class<?>>emptySet(),
				MarshallingFormat.JAXB, Thread.currentThread().getContextClassLoader());

		CommandScript script = new CommandScript();

		switch (processService) {
		case "completeWorkItem":
			script = new CommandScript(Collections.singletonList(
					(KieServerCommand) new DescriptorCommand("ProcessService", processService, new Object[] {
							containerId, processInstanceId, workItemId, "", marshaller.getFormat().getType() })));
			break;
		case "getAvailableSignals":
			script = new CommandScript(
					Collections.singletonList((KieServerCommand) new DescriptorCommand("ProcessService", processService,
							new Object[] { containerId, processInstanceId, marshaller.getFormat().getType() })));
			break;
		default:
			throw new IllegalArgumentException(
					"No marshalling implementation in getCommandString() exists for " + processService);
		}

		return marshaller.marshall(script);
	}

}

Create a new project

Next, navigate to the workbench and create a new project:
Authoring > Project Authoring 
New Item > Project
Finish

Selection_028

Register the Work Item Handler

You will need to upload the jar for your WIH and register it.  Please see more information here: http://fxapps.blogspot.com/2015/04/creating-custom-work-item-handler-in.html

Selection_029

Create a basic process

Once you have registered your work item handler, you can use it to create a basic process.

From the authoring view, New Item > Business Process
Use your new script task with a start and terminal node:

Selection_031.png

Build and deploy the project

Authoring > Project Authoring > Build & Deploy


Taking a step back

Before we kick off our process, let’s take a step back and explain how we expect it to operate within the Kie Server.  This section is written for someone with limited knowledge, so feel free to skip over it if you already understand this stuff. 🙂

Java Message Service API

If you don’t already know, JMS is an API used to send messages between two or more systems.  It is an implementation of the producer-consumer problem.  While it’s not the solution to every problem, it’s a good choice when robustness is priority.  JMS offers many ways to fine-tune message reliability and acknowledgement.

JMS is also a good option when we require loose-coupling.  Sometimes, we may want two components to function without having direct access to one another.  For example, a celebrity might want to accept fan mail, but they would never hand out their personal address.  To send the celebrity a message, we don’t need his/her address — we can send them a message using their PO Box (or being that it’s 2017, a Twitter handle would be more appropriate).  Similarly, a JMS client doesn’t need a server’s address to communicate — it only needs to know the name of the server’s queue.

Message Driven Beans

A message driven bean is an EJB that allows for asynchronous message processing (i.e., message processing that does not depend on the availability of its consumer in order to send a message).

An MDB will implement the MessageListener interface.  Similar to an EventListener, an MDB’s onMessage method will be invoked once a message is passed to the message listener (or in our case, once the message is placed on the specific queue our MDB will be consuming from).

For more information on Message Driven Beans, check out Chapter 4 of the EAP 7.0 documentation.

To listen for incoming JMS Messages, by default, the Kie Server uses the KieServerMDB.

Message Broker

As mentioned above, application components only need access to each others JMS resources in order to communicate with one another.  JMS resources can include Queues, Topics, or Connection Factories.

To utilize these resources efficiently, we use a message broker to transform messages appropriately and send/receive them to/from their respective destinations/sources. EAP 7.0 comes with an embedded message broker, Apache ActiveMQ Artemis.  It is configured using the messaging-activemq subsystem.

JMS Resources

EAP Connection Factories

If you take a look at standalone-full.xml configuration, you will see that EAP comes with three connection factories:


<connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm"/>
<connection-factory name="RemoteConnectionFactory" entries="java:jboss/exported/jms/RemoteConnectionFactory" connectors="http-connector"/>
<pooled-connection-factory name="activemq-ra" transaction="xa" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm"/>

Since we will run the JMS client and the Kie Server within the same container, we don’t need to worry about using the RemoteConnectionFactory.  Instead, our WorkItemHandler will focus on using the activemq-ra connection factory (bound to java:/JmsXA).

Message Queues

The KieServerMDB listens for messages arriving on the request queue, bound to the JNDI queue/KIE.SERVER.REQUEST.

The MDB will send responses to the response queue bound to queue/KIE.SERVER.RESPONSE.

As such, our WIH will need to refer to the request queue JNDI when it sends a request.


3.  Start the Process

Let’s start the process and verify that we receive the expected results in the queue.

  1.  Process Management > Process Definitions
    Selection_030
  2.  Verify the process completes (you can find this screen to the right of the above view)
    Selection_034
  3.  Investigate our message queues using the JBoss Management CLI.In EAP’s /bin directory, run the following command:
./jboss-cli.sh --connect --controller=localhost:9990

To inspect the request and response queues on the kie server:

/deployment=kie-server.war/subsystem=messaging-activemq/server=default/jms-queue=KIE.SERVER.REQUEST:read-resource(include-runtime=true)
/deployment=kie-server.war/subsystem=messaging-activemq/server=default/jms-queue=KIE.SERVER.RESPONSE:read-resource(include-runtime=true)

Since we expect the MDB to have consumed our requests from the WIH, we should have 0 messages in our request queue (indicated by message-count).

Selection_036.png

And since we never actually consume any responses from the MDB, we expect a 1-1 relationship between the number of messages our WIH sent, and the number of responses that exist in the response queue.  This is due in part to the REQUEST_REPLY_PATTERN we used in the prepMessage method of our WIH to define how we want our components to interact.

Selection_037

message.setIntProperty( JMSConstants.INTERACTION_PATTERN_PROPERTY_NAME, JMSConstants.REQUEST_REPLY_PATTERN);

To delete messages from a queue, you can also run the following:

/deployment=kie-server.war/subsystem=messaging-activemq/server=default/jms-queue=KIE.SERVER.RESPONSE:remove-messages

The output will also verify the number of messages that were removed from the queue:

Selection_038.png


Understanding the mechanics of our JMS Resources

Now, let’s dive into some of the mechanics of the JMS resources we will be using.

Connection Pooling / Caching

In our example, both the MDB and our WIH need to access the same request queue. Our WIH will create new resources for each message that is sent to said queue (a new connection, session, producer, etc.).  These resources (in particular, connections and sessions) are often heavy and time-consuming to create, especially when they are created per each and every message.

While creating connection and session objects can be expensive, the trade-off is that they are designed to be reused.  As such, it doesn’t make much sense to not reuse them!  This is where pooling comes into play.

If you are looking for more information on JMS resource caching (and in particular, how it works within JEE Containers/EAP), here is an excellent write up.

XA Connection Factories vs Non-XA Connection Factories

If you recall, paths to connection factories were bound to specific connection factories in our standalone-full.xml.

XA, pooled Connection Factory (i.e., java:/JmsXA)

  • XA: enables the use of global transactions, meaning its scope will span multiple resources
  • Pooled: This connection factory is JCA-based and any connections manufactured from it will come from the EAP’s ManagedConnectionPool (which is made of various configured sub-pools)
  • Since these connections come from the MCP, JMS session and connection caching will automatically be handled for you from inside the container

Generic, non-XA Connection Factory (java:/ConnectionFactory)

  • Non-XA:  enables the use of local transactions; meaning its scope is limited to a single resource
  • Not pooled: this factory is not a JCA managed connection factory and therefore will not automatically take care of any connection/session pooling for you.

For best performance, it is recommended that you use the java:/JmsXA connection factory.

Transacted Sessions  vs Non-transacted Sessions

Notice when we create the session, we have two parameters to define:

  • boolean transacted
  • int acknowledgementMode

I will let you read the documentation I linked for a better understanding of what these parameters are for, but it’s important to know the difference between a non-transacted session, and a transacted session:

  • Transacted Sessions

    Session session = connection.createQueueSession(true, SESSION.SESSION_TRANSACTED);
    

    A transacted session will use a local transaction and treat all sending (or receiving) of messages as a single unit of work.  In a transacted session, messages will not be published/consumed to/from a queue until we manually commit() the session.

     if (session.getTransacted() == true) {
     session.commit();
     }
    
  • Non-transacted Session

    Session session = connection.createQueueSession(false, SESSION.AUTO_ACKNOWLEDGE);
    

    As you can probably guess, a non-transacted session will not group all sends/receives into a single unit of work.  Since our receiver (the MDB) is an implementation of MessageListener, the moment a message arrives on the queue, it is automatically acknowledged once the onMessage method completes.  If for some reason a message is not delivered the first time, ActiveMQ will automatically attempt to resend the message.


5.  Play around with JMS Messaging!

Hopefully, at this point, you have a decent understanding of JMS Messaging and what to expect when a particular JMS Client interacts with our MDB.

The source for our custom WIH can be accessed here.  If you wish to learn more, feel free to play around by observing the performance of different connection factories and session types or pooling configurations… You can also try playing around with sending the MDB different types of commands.

Thanks for reading!  If you have any questions or feel that I’m missing something, please comment below.

3 Comments

  1. Hello Anna, thanks for the helpful post.
    The truth is Iam having difficulties implementing the RemoteConnection Approach. In my case the kie-server runs on Wildfy 10 and lives in a remote pc so Iam trying to connect with the Java JMS API client by using the following code, taken from the mastering Jboss Drools book:

    // private static final String REMOTING_URL = new String(“http-remoting://10.240.56.133:8180”);
    private static final String REMOTING_URL = “remote://10.240.56.133:8180”;

    private static final String USER = “kieserver”;
    private static final String PASSWORD = “kieserver”; //default: kieserver1!

    private static final String INITIAL_CONTEXT_FACTORY = new String(“org.jboss.naming.remote.client.InitialContextFactory”);
    private static final String CONNECTION_FACTORY = new String(“jms/RemoteConnectionFactory”);
    private static final String REQUEST_QUEUE_JNDI = new String(“jms/queue/KIE.SERVER.REQUEST”);
    private static final String RESPONSE_QUEUE_JNDI = new String(“jms/queue/KIE.SERVER.RESPONSE”);

    private KieServicesConfiguration conf;
    private KieServicesClient kieServicesClient;

    @Test
    public void runSimpleRules() throws Exception {

    Properties initialProps = new Properties();
    initialProps.setProperty(InitialContext.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
    initialProps.setProperty(InitialContext.PROVIDER_URL, REMOTING_URL);
    initialProps.setProperty(InitialContext.SECURITY_PRINCIPAL, USER);
    initialProps.setProperty(InitialContext.SECURITY_CREDENTIALS, PASSWORD);
    for (Object keyObj : initialProps.keySet()) {
    String key = (String) keyObj;
    System.setProperty(key, (String) initialProps.get(key));
    }
    InitialContext context = new InitialContext(initialProps);
    //Deploy a container in KIE Server
    KieServicesConfiguration config = KieServicesFactory.newJMSConfiguration(
    context, USER, PASSWORD);

    KieServicesClient client = KieServicesFactory.newKieServicesClient(config);

    client.listContainers();
    }

    But the test always fails with this message:

    09:33:25.390 [main] DEBUG o.j.n.r.client.HaRemoteNamingStore – Failed to connect to server remote://10.240.56.133:8180
    java.net.ConnectException: Operation failed with status WAITING after 5000 MILLISECONDS
    at org.jboss.naming.remote.protocol.IoFutureHelper.get(IoFutureHelper.java:97) ~[jboss-remote-naming-2.0.4.Final.jar:2.0.4.Final]
    at org.jboss.naming.remote.client.HaRemoteNamingStore.failOverSequence(HaRemoteNamingStore.java:198) ~[jboss-remote-naming-2.0.4.Final.jar:2.0.4.Final]
    at org.jboss.naming.remote.client.HaRemoteNamingStore.namingStore(HaRemoteNamingStore.java:149) ~[jboss-remote-naming-2.0.4.Final.jar:2.0.4.Final]
    at org.jboss.naming.remote.client.HaRemoteNamingStore.namingOperation(HaRemoteNamingStore.java:130) ~[jboss-remote-naming-2.0.4.Final.jar:2.0.4.Final]
    at org.jboss.naming.remote.client.HaRemoteNamingStore.lookup(HaRemoteNamingStore.java:272) ~[jboss-remote-naming-2.0.4.Final.jar:2.0.4.Final]
    at org.jboss.naming.remote.client.RemoteContext.lookupInternal(RemoteContext.java:104) [jboss-remote-naming-2.0.4.Final.jar:2.0.4.Final]
    at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:93) [jboss-remote-naming-2.0.4.Final.jar:2.0.4.Final]
    at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:146) [jboss-remote-naming-2.0.4.Final.jar:2.0.4.Final]
    at javax.naming.InitialContext.lookup(InitialContext.java:417) [na:1.8.0_144]
    at com.intrasoft.ssp.drools.admin.DroolsClientJMSTest.testJms(DroolsClientJMSTest.java:47) [test-classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_144]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_144]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_144]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_144]
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) [junit-4.12.jar:4.12]
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) [junit-4.12.jar:4.12]
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) [junit-4.12.jar:4.12]
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) [junit-4.12.jar:4.12]
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12]
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) [junit-rt.jar:na]
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) [junit-rt.jar:na]
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) [junit-rt.jar:na]
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) [junit-rt.jar:na]

    javax.naming.CommunicationException: Failed to connect to any server. Servers tried: [remote://10.240.56.133:8180 (Operation failed with status WAITING after 5000 MILLISECONDS)]
    [Root exception is java.net.ConnectException: Operation failed with status WAITING after 5000 MILLISECONDS]
    at org.jboss.naming.remote.client.HaRemoteNamingStore.failOverSequence(HaRemoteNamingStore.java:240)
    at org.jboss.naming.remote.client.HaRemoteNamingStore.namingStore(HaRemoteNamingStore.java:149)
    at org.jboss.naming.remote.client.HaRemoteNamingStore.namingOperation(HaRemoteNamingStore.java:130)
    at org.jboss.naming.remote.client.HaRemoteNamingStore.lookup(HaRemoteNamingStore.java:272)
    at org.jboss.naming.remote.client.RemoteContext.lookupInternal(RemoteContext.java:104)
    at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:93)
    at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:146)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at com.intrasoft.ssp.drools.admin.DroolsClientJMSTest.testJms(DroolsClientJMSTest.java:47)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    Caused by: java.net.ConnectException: Operation failed with status WAITING after 5000 MILLISECONDS
    at org.jboss.naming.remote.protocol.IoFutureHelper.get(IoFutureHelper.java:97)
    at org.jboss.naming.remote.client.HaRemoteNamingStore.failOverSequence(HaRemoteNamingStore.java:198)
    … 30 more

    The question is: Does the wildfly / kie-server require some configuration in order to accept remote jms connections?
    From my understanding, JMS is ready to remote-use with no – configuration

    WordPress.com / Gravatar.com credentials can be used.

    Like

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s