How do I retrieve a message that is in the JMS Queue? I was looking at this solution: Jboss Messaging JMS, but that just sends and receives right away. If the server restarted, how can I retrieve the message with Java code?
I haven't found anything online; unless, of course, I totally misunderstood how JMS Queues work.
The current version of JBoss uses HornetQ for JMS messaging.
If you are using Java JMS client code your are and attaching to a clustered messaging broker instance, your client should failover to another node.
In a single instance broker configuration, you will get a JMS exception in the client code. This means that you will need to get a new connection and start a new session.
For browsing a queue:
/**
* QueueBrowserGss.java
*
* Created on Sep 24, 2012, 3:52:28 PM
*
* To the extent possible under law, Red Hat, Inc. has dedicated all copyright to this
* software to the public domain worldwide, pursuant to the CC0 Public Domain Dedication. This
* software is distributed without any warranty.
*
* See <http://creativecommons.org/publicdomain/zero/1.0/>.
*
*/
package com.redhat.gss.client;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* #author grovedc
*
*/
public class QueueBrowserGss {
private static final Log logger = LogFactory.getLog(QueueBrowserGss.class);
#SuppressWarnings("unchecked")
public static void main(String[] args) {
QueueConnection queueConnection = null;
Queue queue = null;
QueueConnectionFactory queueConnFactory = null;
QueueBrowser queueBrowser = null;
QueueSession queueSession = null;
List<Object> messages = new ArrayList<Object>(7000);
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
properties.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
// properties.put(Context.PROVIDER_URL, "jnp://" + server + ":" + port);
properties.put("Context.PROVIDER_URL", "jnp://10.0.0.150:1100");
try {
InitialContext ctx = new InitialContext(properties);
queue = (Queue) ctx.lookup("queue/D");
queueConnFactory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
queueConnection = queueConnFactory.createQueueConnection();
queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queueBrowser = queueSession.createBrowser(queue);
queueConnection.start();
for (Enumeration<Object> e = queueBrowser.getEnumeration(); e.hasMoreElements();) {
messages.add(e.nextElement());
}
logger.info("Messages are retrieved from queue. Process completed on: " + new Date());
logger.info("Number of Messages present: " + messages.size());
} catch (Exception ex) {
logger.error(String.format("Exception Occured : %s", ex.getMessage()), ex);
} finally {
try {
if (queueConnection != null)
queueConnection.stop();
} catch (JMSException e) {
logger.error(e);
}
}
}
}
The jnp protocol and ports are for JBoss Messaging.
Depending on your use-case, you can use a tool like JMSToolBox to browse/post/delete etc.. the content of JBoss/HornetQ destinations
You have to make a QueueBrowserand enumerate through them. Example code:
// Create the connection
InitialContext context = new InitialContext(properties);
QueueConnectionFactory queueConnFactory = (QueueConnectionFactory) context.lookup("ConnectionFactory");
QueueConnection conn = queueConnFactory.createQueueConnection();
Queue queue = (Queue) context.lookup("/queue/Test");
QueueSession session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
// Start the connection
conn.start()
// Create a QueueBrowser using the session
QueueBrowser queueBrowser = session.createBrowser(queue);
Enumeration e = queueBrowser.getEnumeration();
// Iterate through the queue
while(e.hasMoreElements()) {
Message msg = (Message) e.nextElement();
TextMessage txtMsg = (TextMessage) msg;
System.out.println(txtMsg.getText());
}
As this is just an example, you can change the TextMessage part to suit your needs.
Related
I have a spring-batch which browses Queue messages, this queue supposed to contain a huge number of messages. then it takes a lot of time to treat all of them. therefore i thought about multi-Threading to deal with the issue, but it's not clear for me yet.
Here is an example of browsing a Queue without multithreading:
import java.net.URISyntaxException;
import java.util.Enumeration;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
public class JmsQueueBrowseExample {
public static void main(String[] args) throws URISyntaxException, Exception {
Connection connection = null;
try {
// Producer
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
"tcp://localhost:61616");
connection = connectionFactory.createConnection();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("browseQueue");
MessageConsumer consumer = session.createConsumer(queue);
connection.start();
System.out.println("Browse through the elements in queue");
QueueBrowser browser = session.createBrowser(queue);
Enumeration e = browser.getEnumeration();
//Multithreading here
while (e.hasMoreElements()) {
TextMessage message = (TextMessage) e.nextElement();
System.out.println("Browse [" + message.getText() + "]");
}
System.out.println("Done");
browser.close();
session.close();
} finally {
if (connection != null) {
connection.close();
}
}
}
}
Thank you
Other than the close methods the JMS API Resources such as Session, MessageConsumer, QueueBrowser etc are not meant to be used by more than a single thread of control and as such trying to concurrently iterate over the messages returned from a QueueBrowser enumeration is likely to result is errors.
The JMS specification adds some insight into concurrency with session resources.
There are no restrictions on the number of threads that can use a Session object or those it creates. The restriction is that the resources of a Session should not be used concurrently by multiple threads. It is up to the user to insure that this concurrency restriction is met. The simplest way to do this is to use one thread. In the case of asynchronous delivery, use one thread for setup in stopped mode and then start asynchronous delivery. In more complex cases the user must provide explicit synchronization.
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
public class MessageSender {
public static ConnectionFactory factory = null;
public static Connection connection = null;
public static Session session = null;
public static Destination destination = null;
public static MessageProducer producer = null;
public static void sendMessage(String queueName,String messageContent) {
try {
factory = new ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_BROKER_URL);
connection = factory.createConnection();
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue(queueName);
producer = session.createProducer(destination);
TextMessage message = session.createTextMessage();
message.setText(messageContent);
producer.send(message);
System.out.println("Sent: " + message.getText() );
} catch (JMSException e) {
e.printStackTrace();
}
}
}
Above is my java JMS code to push messages to the queue. Every time I want push message to queue, I used to invoke like below
MessageSender.sendMessage("orderdetailsQueue","OrderReceivedIdB6789");
so for each message it invoke new connection.start(). How can I generalize this?
Creating connection factory and then a connection in every sendMessage is probably not a good idea.
You can move this connection factory initialization part to a singleton util class which creates the connection factory only once when that util class is instantiated. Also use the PooledConnectionFactory instead of normal connection factory which creates a pool of connections, sessions and producers. The sendMessage should get the connection by calling connectionUtil.getConnection(). The rest of the code in sendMessage looks fine except you need to release the session, producer and connection in finally by calling close() on these objects.
Pooled Connection Factory
I am using jboss 5.1.0 GA. I am trying to create a helloworldjMS.java. The code is as follows,
import java.util.Hashtable;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
public class HelloWorldJMS {
public static void main(String[] args) {
try {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
env.put(Context.PROVIDER_URL, "jnp://localhost:1099");
env.put(Context.URL_PKG_PREFIXES,
"org.jboss.naming:org.jnp.interfaces");
// Create the initial context
Context ctx = new InitialContext(env);
// Lookup the JMS connection factory from the JBoss 5.1 object store
ConnectionFactory connectionFactory = (ConnectionFactory) ctx
.lookup("ConnectionFactory");
// Lookup a queue from the JBoss 5.1 object store
Queue queue = (javax.jms.Queue) ctx.lookup("/queue/DLQ");
// Create a connection to the JBoss 5.1 Message Service
Connection connection = connectionFactory.createConnection();
// Create a session within the connection
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
// Create a message producer to put messages on the queue
MessageProducer messageProducer = session.createProducer(queue);
// Create and send a message to the queue
TextMessage textMessage = session.createTextMessage();
textMessage.setText("Hello World");
System.out.println("Sending Message: " + textMessage.getText());
messageProducer.send(textMessage);
// Create a message consumer
MessageConsumer messageConsumer = session.createConsumer(queue);
// Start the Connection created
connection.start();
// Receive a message from the queue.
Message msg = messageConsumer.receive();
// Retrieve the contents of the message.
if (msg instanceof TextMessage) {
TextMessage txtMsg = (TextMessage) msg;
System.out.println("Read Message: " + txtMsg.getText());
}
// Close the session and connection resources.
session.close();
connection.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
I am getting the following error,
org.jboss.jms.exception.MessagingNetworkFailureException
at org.jboss.jms.client.delegate.DelegateSupport.handleThrowable(DelegateSupport.java:245)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate.org$jboss$jms$client$delegate$ClientConnectionFactoryDelegate$createConnectionDelegate$aop(ClientConnectionFactoryDelegate.java:187)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.invokeNext(ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.java)
at org.jboss.jms.client.container.StateCreationAspect.handleCreateConnectionDelegate(StateCreationAspect.java:83)
at org.jboss.aop.advice.org.jboss.jms.client.container.StateCreationAspect_z_handleCreateConnectionDelegate_328011903.invoke(StateCreationAspect_z_handleCreateConnectionDelegate_328011903.java)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.invokeNext(ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.java)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate.createConnectionDelegate(ClientConnectionFactoryDelegate.java)
at org.jboss.jms.client.JBossConnectionFactory.createConnectionInternal(JBossConnectionFactory.java:205)
at org.jboss.jms.client.JBossConnectionFactory.createConnection(JBossConnectionFactory.java:87)
at org.jboss.jms.client.JBossConnectionFactory.createConnection(JBossConnectionFactory.java:82)
at HelloWorldJMS.main(HelloWorldJMS.java:67)
Caused by: org.jboss.remoting.ConnectionFailedException: Timed out trying to create control socket
at org.jboss.remoting.transport.bisocket.BisocketClientInvoker.handleConnect(BisocketClientInvoker.java:276)
at org.jboss.remoting.MicroRemoteClientInvoker.connect(MicroRemoteClientInvoker.java:309)
at org.jboss.remoting.Client.connect(Client.java:1612)
at org.jboss.remoting.Client.connect(Client.java:515)
at org.jboss.remoting.callback.ServerInvokerCallbackHandler.connect(ServerInvokerCallbackHandler.java:168)
at org.jboss.remoting.ServerInvoker.getCallbackHandler(ServerInvoker.java:2064)
at org.jboss.remoting.ServerInvoker.handleInternalInvocation(ServerInvoker.java:1646)
at org.jboss.remoting.transport.bisocket.BisocketServerInvoker.handleInternalInvocation(BisocketServerInvoker.java:863)
at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:878)
at org.jboss.remoting.transport.socket.ServerThread.completeInvocation(ServerThread.java:744)
at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:697)
at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:551)
at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:232)
at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvoker.java:163)
at org.jboss.remoting.Client.invoke(Client.java:1550)
at org.jboss.remoting.Client.addCallbackListener(Client.java:1619)
at org.jboss.remoting.Client.addListener(Client.java:913)
at org.jboss.jms.client.remoting.JMSRemotingConnection.addInvokerCallbackHandler(JMSRemotingConnection.java:230)
at org.jboss.jms.client.remoting.JMSRemotingConnection.start(JMSRemotingConnection.java:340)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate.org$jboss$jms$client$delegate$ClientConnectionFactoryDelegate$createConnectionDelegate$aop(ClientConnectionFactoryDelegate.java:154)
... 9 more
I have the following jars,
concurrent.jar,javassist-3.10.0.GA.jar,jboss-aop-client.jar,jboss-common-core-2.2.10.GA.jar,jboss-common.jar, jboss-j2ee.jar , jboss-mdr-2.0.1.GA.jar, jboss-messaging-client.jar, jboss-remoting.jar, jbossmq.jar, jetty-session-redis-2.3.ga-serialjboss.jar, jnpserver.jar.
I know this is very old jboss questions. But I tried various suggestions, could not find any way. So, i am posting the question. So kindly provide some suggestions.
Thanks
Remove jboss-remoting.jar and add jboss-remoting-4.2.2.GA.jar
I am trying to set the Accounting Token on the a message which my system received from inbound queue. I am setting this token using the following.
msg.setObjectProperty(JmsConstants.JMS_IBM_MQMD_ACCOUNTINGTOKEN,value)
Also I have the following properties in my JmsSUpport class
((JmsDestination) dest).setBooleanProperty(WMQConstants.WMQ_MQMD_READ_ENABLED, true);
((JmsDestination) dest).setBooleanProperty(WMQConstants.WMQ_MQMD_WRITE_ENABLED, true);
((MQDestination) dest).setMQMDWriteEnabled(true);
((MQDestination) dest).setMQMDReadEnabled(true);
((MQDestination) dest).setTargetClient(JMSC.MQJMS_CLIENT_NONJMS_MQ);
Since the outbound queue is MQDestination I have to set the above properties. Now I am observing that I am correctly setting the value on the outbound message. But when the other application reads the message from the MQ it has default value for Accounting Token. Could this be because the MQ is configured in such way to override the value? Or is it because the other application is not reading MQ message correctly? Or should I be using any other property to enable accounting token?
Is it because I am setting ((MQDestination) dest).setTargetClient(JMSC.MQJMS_CLIENT_NONJMS_MQ); the msg gets stripped of MQMD Headers?
No, MQMD is never stripped off. You have to set identity context on the destination before sending a message. Otherwise queue manager will ignore the Accounting token. Please see the sample code:
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import com.ibm.msg.client.jms.JmsConnectionFactory;
import com.ibm.msg.client.jms.JmsFactoryFactory;
import com.ibm.msg.client.jms.JmsDestination;
import com.ibm.msg.client.wmq.WMQConstants;
import com.ibm.msg.client.jms.JmsConstants;
import com.ibm.mq.jms.MQDestination;
public class AccountingTokenDemo {
public static void main(String[]args) {
// TODO Auto-generated method stub
AccountingTokenDemo demo = new AccountingTokenDemo();
demo.putMessageWithAccountingToken();
}
public void putMessageWithAccountingToken() {
JmsConnectionFactory cf = null;
Connection connection = null;
Session session = null;
Destination reqQ = null;
MessageProducer producer = null;
try {
// Create a connection factory
JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
cf = ff.createConnectionFactory();
// Set the properties
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_BINDINGS);
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, "QM2");
// Create JMS objects
connection = cf.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create a 32 byte accounting toke
byte [] accountingToken = new byte[32];
byte b = 'a';
for(int i=0; i < 32;i++)
accountingToken[i] = b++;
// Create destination to send requests
reqQ = session.createQueue("queue:///REQUESTQ");
((MQDestination) reqQ).setTargetClient(WMQConstants.WMQ_CLIENT_NONJMS_MQ);
((JmsDestination) reqQ).setBooleanProperty(WMQConstants.WMQ_MQMD_READ_ENABLED, true);
((JmsDestination) reqQ).setBooleanProperty(WMQConstants.WMQ_MQMD_WRITE_ENABLED, true);
((MQDestination) reqQ).setMQMDMessageContext(WMQConstants.WMQ_MDCTX_SET_IDENTITY_CONTEXT);
// Create producer
producer = session.createProducer(reqQ);
// Create a request message
Message requestMessage = session.createTextMessage("Setting Accounting token on message");
requestMessage.setObjectProperty(JmsConstants.JMS_IBM_MQMD_ACCOUNTINGTOKEN, accountingToken);
// Send it off
producer.send(requestMessage);
}catch(Exception ex){
System.out.println(ex);
}
}
}
What are the options available to develop Java applications using Service Bus for Windows?
Java Message Broker API - This need ACS to work with, which SB for Win doesnt support.
AMQP - This doesnt seem to work on SB for Windows, I keep getting error
org.apache.qpid.amqp_1_0.client.Sender$SenderCreationException: Peer did not create remote endpoint for link, target:
While the same code works with Azure SB. So AMQP on SB for Windows seems to be not fully working?
Correct me if I have missed something?
Update
To test AMQP on local machine, this is what I did
Installed Service bus 1.1 on my local machine
Took the sample mentioned here http://www.windowsazure.com/en-us/develop/java/how-to-guides/service-bus-amqp/
Created a new namespace on my local machine
Specified the following connection string in servicebus.properties (which is correctly referred in the code
connectionfactory.SBCF = amqps://<username>:<password>#<MachineName>:5671/StringAnalyzerNS/
queue.QUEUE = queue1
Code is updated with certificates.
At runtime I get this error
javax.jms.JMSException: Peer did not create remote endpoint for link, target: queue1
at org.apache.qpid.amqp_1_0.jms.impl.MessageProducerImpl.<init>(MessageProducerImpl.java:77)
at org.apache.qpid.amqp_1_0.jms.impl.SessionImpl.createProducer(SessionImpl.java:348)
at org.apache.qpid.amqp_1_0.jms.impl.SessionImpl.createProducer(SessionImpl.java:63)
at com.stringcompany.Analyzer.SimpleSenderReceiver.<init>(SimpleSenderReceiver.java:70)
at com.stringcompany.Analyzer.SimpleSenderReceiver.main(SimpleSenderReceiver.java:95)
Caused by: org.apache.qpid.amqp_1_0.client.Sender$SenderCreationException: Peer did not create remote endpoint for link, target: queue1
at org.apache.qpid.amqp_1_0.client.Sender.<init>(Sender.java:171)
at org.apache.qpid.amqp_1_0.client.Sender.<init>(Sender.java:104)
at org.apache.qpid.amqp_1_0.client.Sender.<init>(Sender.java:97)
at org.apache.qpid.amqp_1_0.client.Sender.<init>(Sender.java:83)
at org.apache.qpid.amqp_1_0.client.Sender.<init>(Sender.java:69)
at org.apache.qpid.amqp_1_0.client.Sender.<init>(Sender.java:63)
at org.apache.qpid.amqp_1_0.client.Session.createSender(Session.java:74)
at org.apache.qpid.amqp_1_0.client.Session.createSender(Session.java:66)
at org.apache.qpid.amqp_1_0.jms.impl.MessageProducerImpl.<init>(MessageProducerImpl.java:72)
... 4 more
javax.jms.JMSException: Session remotely closed
With the same code If I point to Azure service bus by setting the SB namespace and queue like below
connectionfactory.SBCF = amqps://<Policy name>:<Sec. Key>#<ns>.servicebus.windows.net
queue.QUEUE = testq
This works, messages are exchanged.
Here is the code if someone wants to try it
package com.stringcompany.Analyzer;
//SimpleSenderReceiver.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Hashtable;
import java.util.Random;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
public class SimpleSenderReceiver implements MessageListener {
private static boolean runReceiver = true;
private Connection connection;
private Session sendSession;
private Session receiveSession;
private MessageProducer sender;
private MessageConsumer receiver;
private static Random randomGenerator = new Random();
public SimpleSenderReceiver() throws Exception {
// Configure JNDI environment
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.qpid.amqp_1_0.jms.jndi.PropertiesFileInitialContextFactory");
env.put(Context.PROVIDER_URL, "D:\\Java\\Azure\\workspace\\Analyzer\\src\\main\\resources\\servicebus.properties");
Context context = new InitialContext(env);
// Lookup ConnectionFactory and Queue
ConnectionFactory cf = (ConnectionFactory) context.lookup("SBCF");
System.out.println("cf:"+cf);
// Create Connection
connection = cf.createConnection();
System.out.println("connection :"+connection);
connection.setExceptionListener(new ExceptionListener() {
public void onException(JMSException arg0) {
System.err.println(arg0);
}
});
connection.start();
// Create sender-side Session and MessageProducer
sendSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
System.out.println("Session open");
Destination queue = (Destination) context.lookup("QUEUE");
System.out.println("queue:"+queue);
sender = sendSession.createProducer(queue);
Queue q=(Queue) queue;
System.out.println(sender.getDestination());
System.out.println("sender:"+sender);
if (runReceiver) {
System.out.println("Waitng for new message");
// Create receiver-side Session, MessageConsumer,and MessageListener
receiveSession = connection.createSession(false,
Session.CLIENT_ACKNOWLEDGE);
receiver = receiveSession.createConsumer(queue);
receiver.setMessageListener(this);
connection.start();
}
}
public static void main(String[] args) {
try {
if ((args.length > 0) && args[0].equalsIgnoreCase("sendonly")) {
runReceiver = false;
}
//System.setProperty("javax.net.debug","ssl");
System.setProperty("javax.net.ssl.trustStore","D:\\Java\\Azure\\workspace\\Analyzer\\src\\main\\resources\\SBKeystore.keystore");
System.setProperty("log4j.configuration","D:\\Java\\Azure\\workspace\\Analyzer\\src\\main\\resources\\log4j.properties");
SimpleSenderReceiver simpleSenderReceiver = new SimpleSenderReceiver();
System.out
.println("Press [enter] to send a message. Type 'exit' + [enter] to quit.");
BufferedReader commandLine = new java.io.BufferedReader(
new InputStreamReader(System.in));
while (true) {
String s = "Message";//commandLine.readLine();
if (s.equalsIgnoreCase("exit")) {
simpleSenderReceiver.close();
System.exit(0);
} else {
simpleSenderReceiver.sendMessage();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendMessage() throws JMSException {
TextMessage message = sendSession.createTextMessage();
message.setText("Test AMQP message from JMS");
long randomMessageID = randomGenerator.nextLong() >>> 1;
message.setJMSMessageID("ID:" + randomMessageID);
sender.send(message);
System.out.println("Sent message with JMSMessageID = "
+ message.getJMSMessageID());
}
public void close() throws JMSException {
connection.close();
}
public void onMessage(Message message) {
try {
System.out.println("Received message with JMSMessageID = "
+ message.getJMSMessageID());
message.acknowledge();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Hi we had the same problems and thankfully MS updated their documentation to show how to do this correctly. :
http://msdn.microsoft.com/en-us/library/dn574799.aspx
The simplest answer to the question is as you should URL Encode the SASPolicyKey.
connectionfactory.SBCF = amqps://[SASPolicyName]:[SASPolicyKey]#[namespace].servicebus.windows.net
Where SASPolicyKey should be URL-Encoded.
AMQP 1.0 is supported with Service Bus 1.1 for windows server. Basically there are two differences between the cloud and on-prem usage of AMQP in ServiceBus:
1. Addressing: You will need to build an AMQP connection strings (and will need DNS in case you're looking for HA)
2. Authentication: You will need to use domain joined accounts as ACS is not there on-prem. You will also need to distribute your SB certificate to your clients.
Ok, I have sorted the first issue (Java Message Broker API not supporting SAS endpoint), by writing a wrapper which will seamlessly work with existing API. You can get the library from this GitHub repository. With this, I can develop/test my Java application on local service bus environment and host it on Azure / On-Premise Service Bus farm.
https://github.com/Dhana-Krishnasamy/ServiceBusForWindows-SASWrapper
The sender and receiver Queues you will have to configure differently. Here is an example of my working configuration (servicebus.properties):
connectionfactory.SBCF = amqps://$PolicyName:$UrlEncodedKey#$Your-EventHub-NamespaceName.servicebus.windows.net
queue.EventHubSender=$YourEventHubName
queue.EventHubReceiver=$YourEventHubName/ConsumerGroups/$YourConsumerGroupName/Partitions/1
Replace appropriately your own '$' items in there.
The Shared Policy Key has to be URL encoded.
Make sure that your sender will reference the 'EventHubSender' defined in this config and the receiver will reference the 'EventHubReciever'.
Grab the Azure Java SDK from http://www.windowsazure.com/en-us/develop/java/ and then follow this guide: http://www.windowsazure.com/en-us/develop/java/how-to-guides/service-bus-queues/