org.zeromq.ZMQException: Errno 48 : Address already in use - zeromq

I am trying to implement a pub-sub example using ZeroMQ.
I run the publisher's code in a docker container and the subscriber's code in another one.
My subscriber is:
private ZMQ.Context context;
{
context = ZMQ.context(1);
}
public void receive() {
System.out.println("Getting subscriber, listening to tcp://localhost:5565");
getSubscriber();
byte[] raw;
System.out.println("Watching for new Event messages...");
try {
while (!Thread.currentThread().isInterrupted()) {
raw = subscriber.recv();
System.out.println("Event received " + raw);
}
} catch (Exception e) {
System.out.println("Unable to receive messages via ZMQ: " + e.getMessage());
}
if (subscriber != null)
subscriber.close();
subscriber = null;
System.out.println("Attempting restart of Event message watch.");
receive();
}
private ZMQ.Socket getSubscriber() {
if (subscriber == null) {
try {
subscriber = context.socket(ZMQ.SUB);
subscriber.connect("tcp://localhost:5565");
subscriber.subscribe("".getBytes());
} catch (Exception e) {
System.out.println("Unable to get a ZMQ subscriber. Error: " + e);
subscriber = null;
}
}
return subscriber;
}
And my publisher is:
private ZMQ.Context context;
{
context = ZMQ.context(1);
}
public synchronized void sendEventMessage(Event event) {
try {
if (publisher == null) {
getPublisher();
}
if (publisher != null) {
publisher.send(event);
}
} catch (Exception e) {
System.out.println("Unable to send message via ZMQ");
}
}
private void getPublisher() {
try {
if (publisher == null) {
publisher = context.socket(ZMQ.PUB);
publisher.bind("tcp://192.168.32.9:5565"); //where 192.168.32.9 is the IP of the subscriber's docker container
Thread.sleep(PUB_UP_SLEEP); // allow subscribers to connect
}
} catch (Exception e) {
System.out.println("Unable to get a publisher. Error: " + e);
publisher = null;
}
}
When I start the application, I register a subscriber and the logs are:
[2018-12-10 08:01:02.138] boot - 1 INFO [main] --- ZeroMQEventSubscriber: Getting subscriber, listening to tcp://localhost:5565
[2018-12-10 08:01:02.249] boot - 1 INFO [main] --- ZeroMQEventSubscriber: Watching for new Event messages...
My problem is that when I invoke sendEventMessage, the subscriber does not receive anything and on the publisher I get this error:
[2018-12-10 08:54:16.388] boot - 1 ERROR [task-scheduler-5] --- ZeroMQEventPublisherImpl: Unable to get a publisher. Error: org.zeromq.ZMQException: Errno 48 : Address already in use
Any ideas why I cannot bind to the address where the subscriber has connected?

Related

IBM MQ JMSWMQ0018: Failed to connect to queue manager 'MY_LOCAL_QM' with connection mode 'Client' and host name 'MY_LOCAL_QM(1401)'

I created a queue manager, queue, channel(Server-connection).
When I try to send a message, see this error:
com.ibm.msg.client.jms.DetailedIllegalStateException: JMSWMQ0018: Failed to connect to queue manager 'MY_LOCAL_QM' with connection mode 'Client' and host name 'epspa(1401)'.
Check the queue manager is started and if running in client mode, check there is a listener running. Please see the linked exception for more information.
Maybe I need to set a user to queue manager? Because I use the same java code, but try to connect to another queue manager, and it works fine. But it doesn't work with my queue manager.
IBM MQ installed on another PC.
private static final String HOST = "epspa";
private static final int PORT = 1401;
private static final String CHANNEL = "API.SVRCONN_LOCAL";
private static final String QMN = "MY_LOCAL_QM";
private static final String QUEUE_NAME = "API.QUEUE_NAME";
private static final String message ="message";
public static String sendMessage(String message) {
String result = "Error";
try {
MQQueueConnectionFactory cf = new MQQueueConnectionFactory();
cf.setHostName(HOST);
cf.setChannel(CHANNEL);
cf.setPort(PORT);
cf.setQueueManager(QMN);
cf.setTransportType(WMQConstants.WMQ_MESSAGE_BODY_MQ);
Destination destination = null;
MessageProducer producer = null;
Connection c = cf.createConnection();
Session s = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = s.createQueue(QUEUE_NAME);
producer = s.createProducer(destination);
TextMessage tmo = s.createTextMessage();
((MQDestination) destination).setMessageBodyStyle
(WMQConstants.WMQ_MESSAGE_BODY_MQ);
tmo.setIntProperty(WMQConstants.JMS_IBM_CHARACTER_SET, 1208);
tmo.setIntProperty(WMQConstants.JMS_IBM_ENCODING,546);
tmo.setText(message);
producer.send(tmo);
result = "Success!";
} catch (JMSException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
cf.setTransportType(WMQConstants.WMQ_MESSAGE_BODY_MQ);
Well, that's not correct. It should be:
cf.setTransportType(WMQConstants.WMQ_CM_CLIENT);
JMSWMQ0018: Failed to connect to queue manager
A JMS error does not give enough details about what MQ is complaining about. You need to output the LinkedException.
catch (JMSException e)
{
if (e != null)
{
System.err.println("getLinkedException()=" + e.getLinkedException());
System.err.println(e.getLocalizedMessage());
e.printStackTrace();
}
}
Are you sure that port # of 1401 is correct? The default port # for MQ is 1414. Start runmqsc against your queue manager. i.e.
runmqsc MY_LOCAL_QM
then issue the following command:
DIS LISTENER(LISTENER.TCP)
what value is given for the PORT attribute?
tmo.setIntProperty(WMQConstants.JMS_IBM_CHARACTER_SET, 1208);
tmo.setIntProperty(WMQConstants.JMS_IBM_ENCODING,546);
Why are you setting the CCSID and Encoding? Why don't you let JMS & MQ take care of it?
Here is a fully functioning JMS program that puts a message to a queue:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import javax.jms.*;
import com.ibm.mq.jms.*;
import com.ibm.msg.client.wmq.WMQConstants;
/**
* Program Name
* MQTestJMS11
*
* Description
* This java JMS class will connect to a remote queue manager and put a message to a queue.
*
* Sample Command Line Parameters
* -m MQA1 -h 127.0.0.1 -p 1414 -c TEST.CHL -q TEST.Q1 -u UserID -x Password
*
* #author Roger Lacroix
*/
public class MQTestJMS11
{
private static final SimpleDateFormat LOGGER_TIMESTAMP = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
private Hashtable<String,String> params;
private MQQueueConnectionFactory mqQCF = null;
/**
* The constructor
*/
public MQTestJMS11()
{
super();
params = new Hashtable<String,String>();
}
/**
* Make sure the required parameters are present.
* #return true/false
*/
private boolean allParamsPresent()
{
boolean b = params.containsKey("-h") && params.containsKey("-p") &&
params.containsKey("-c") && params.containsKey("-m") &&
params.containsKey("-q") &&
params.containsKey("-u") && params.containsKey("-x");
if (b)
{
try
{
Integer.parseInt((String) params.get("-p"));
}
catch (NumberFormatException e)
{
b = false;
}
}
return b;
}
/**
* Extract the command-line parameters and initialize the MQ variables.
* #param args
* #throws IllegalArgumentException
*/
private void init(String[] args) throws IllegalArgumentException
{
if (args.length > 0 && (args.length % 2) == 0)
{
for (int i = 0; i < args.length; i += 2)
{
params.put(args[i], args[i + 1]);
}
}
else
{
throw new IllegalArgumentException();
}
if (allParamsPresent())
{
try
{
mqQCF = new MQQueueConnectionFactory();
mqQCF.setQueueManager((String) params.get("-m"));
mqQCF.setHostName((String) params.get("-h"));
mqQCF.setChannel((String) params.get("-c"));
mqQCF.setTransportType(WMQConstants.WMQ_CM_CLIENT);
try
{
mqQCF.setPort(Integer.parseInt((String) params.get("-p")));
}
catch (NumberFormatException e)
{
mqQCF.setPort(1414);
}
}
catch (JMSException e)
{
if (e != null)
{
MQTestJMS11.logger("getLinkedException()=" + e.getLinkedException());
MQTestJMS11.logger(e.getLocalizedMessage());
e.printStackTrace();
}
throw new IllegalArgumentException();
}
catch (Exception e)
{
MQTestJMS11.logger(e.getLocalizedMessage());
e.printStackTrace();
throw new IllegalArgumentException();
}
}
else
{
throw new IllegalArgumentException();
}
}
/**
* Test the connection to the queue manager.
* #throws MQException
*/
private void testConn()
{
QueueConnection conn = null;
QueueSession session = null;
Queue myQ = null;
try
{
conn = mqQCF.createQueueConnection((String) params.get("-u"), (String) params.get("-x"));
conn.start();
session = conn.createQueueSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
MQTestJMS11.logger("successfully connected.");
myQ = session.createQueue((String) params.get("-q"));
MQDestination mqd = (MQDestination) myQ;
mqd.setTargetClient(WMQConstants.WMQ_CLIENT_JMS_COMPLIANT);
// mqd.setTargetClient(WMQConstants.WMQ_CLIENT_NONJMS_MQ);
sendMsg( session, myQ);
}
catch (JMSException e)
{
if (e != null)
{
MQTestJMS11.logger("getLinkedException()=" + e.getLinkedException());
MQTestJMS11.logger(e.getLocalizedMessage());
e.printStackTrace();
}
}
catch (Exception e)
{
MQTestJMS11.logger(e.getLocalizedMessage());
e.printStackTrace();
}
finally
{
try
{
if (session != null)
session.close();
}
catch (Exception ex)
{
MQTestJMS11.logger("session.close() : " + ex.getLocalizedMessage());
}
try
{
if (conn != null)
conn.stop();
}
catch (Exception ex)
{
MQTestJMS11.logger("connection.stop() : " + ex.getLocalizedMessage());
}
try
{
if (conn != null)
conn.close();
}
catch (Exception ex)
{
MQTestJMS11.logger("connection.close() : " + ex.getLocalizedMessage());
}
}
}
/**
* Send a message to a queue.
* #throws MQException
*/
private void sendMsg(QueueSession session, Queue myQ) throws JMSException
{
QueueSender sender = null;
try
{
TextMessage msg = session.createTextMessage();
msg.setText("Nice simple test. Time in 'ms' is -> " + System.currentTimeMillis());
// msg.setJMSReplyTo(tq);
// msg.setJMSDeliveryMode( DeliveryMode.NON_PERSISTENT);
MQTestJMS11.logger("Sending request to " + myQ.getQueueName());
MQTestJMS11.logger("");
sender = session.createSender(myQ);
sender.send(msg);
}
finally
{
try
{
if (sender != null)
sender.close();
}
catch (Exception ex)
{
MQTestJMS11.logger("sender.close() : " + ex.getLocalizedMessage());
}
}
}
/**
* A simple logger method
* #param data
*/
public static void logger(String data)
{
String className = Thread.currentThread().getStackTrace()[2].getClassName();
// Remove the package info.
if ( (className != null) && (className.lastIndexOf('.') != -1) )
className = className.substring(className.lastIndexOf('.')+1);
System.out.println(LOGGER_TIMESTAMP.format(new Date())+" "+className+": "+Thread.currentThread().getStackTrace()[2].getMethodName()+": "+data);
}
/**
* mainline
* #param args
*/
public static void main(String[] args)
{
MQTestJMS11 write = new MQTestJMS11();
try
{
write.init(args);
write.testConn();
}
catch (IllegalArgumentException e)
{
MQTestJMS11.logger("Usage: java MQTestJMS11 -m QueueManagerName -h host -p port -c channel -q JMS_Queue_Name -u UserID -x Password");
System.exit(1);
}
catch (Exception e)
{
MQTestJMS11.logger(e.getLocalizedMessage());
System.exit(1);
}
System.exit(0);
}
}

Store the message which is received/sent to the queue using JmsListener

Is there any way to put interceptor in jms listener..requirement is to store the request and response while reading and writing to message queue
#JmsListener(destination = "${ibm.mq.queueName}", containerFactory = "containerFactory")
public void readAndProcessMessage(Message<?> message) throws Exception {
UnProcessedEvent unProcessedEvent;
String eventMessage = message.getPayload().toString();
log.info("Received an event: " + eventMessage);
try {
String iban = getIban(eventMessage);
// Identifying Topic
for (Mandate mandate : configProperties.getMandates()) {
for (Topic topic : mandate.getTopic()) {
if (topic.getAccountNumber().equals(iban)) {
publisherService.publishEvent(iban, eventMessage);
return;
}
}
}
unProcessedEvent = UnProcessedEvent.builder().incomingReqPayload((eventMessage)).reason("No Topic Found")
.reasonCode(HttpStatus.BAD_REQUEST.toString()).build();
unprocessedEventRepository.save(unProcessedEvent);
} catch (JAXBException e) {
log.info("Exception while parsing the event message: " + e.getMessage());
unProcessedEvent = UnProcessedEvent.builder().incomingReqPayload((eventMessage)).reason("Bad Request")
.reasonCode(HttpStatus.BAD_REQUEST.toString()).build();
unprocessedEventRepository.save(unProcessedEvent);
}
}

TcpSocketClient- UnhandledException when I try read a response inside of a Task that not arrived yet

I'm using this library(https://github.com/rdavisau/sockets-for-pcl) to communicate with a TCP Server, that sends me when a event was generated, then, I have to verify all the time if the TCP Server sent to me a event, but if I try read anything before the TCP Server sends me, it's thrown the UnhandledException, but it only happens if I read inside a Task, in the main thread it thrown a timeout exception, the exception that I expected to happen in Task.
Someone can help me? Thanks. below is my code.
public class CentralTcpService
{
#region ConnectTcpAsync
public async void ConnectTcpAsync()
{
try
{
_sockecClient = new TcpSocketClient();
await _sockecClient.ConnectAsync(Central.Ip, Central.Port);
_writter = new ExtendedBinaryWriter(_sockecClient.WriteStream);
_reader = new ExtendedBinaryReader(_sockecClient.ReadStream);
_writter.WriteString(EvenNotProtocol.MobileReceiverCommand);
_sockecClient.ReadStream.ReadTimeout = int.MaxValue;
EnableTcpService();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
#endregion
#region TcpService
private void EnableTcpService()
{
_cancelationTcpService = new CancellationTokenSource();
new Task(StartService, _cancelationTcpService.Token, TaskCreationOptions.LongRunning).Start();
}
private void StartService()
{
while (!_cancelationTcpService.Token.IsCancellationRequested)
{
var ev = EvenNotProtocol.DeserializeEvent(_reader);
if (ev == null) continue;
_writter.WriteString(EvenNotProtocol.MobileOkCommand);
EventReceived?.Invoke(this, new CentralTcpEventArgs(ev));
}
}
}
public class EvenNotProtocol
{
public static Event DeserializeEvent(ExtendedBinaryReader reader)
{
try
{
reader.SkipBytes(1);
.....
}
catch (IOException e)
{
return null;
}
}
}

Trying to get the message from server but receive call gets blocked

// This is send message from where I am sending message to server, Its working fine
public void sendMessage(com.google.protobuf.Message sendmessage) {
try {
createJmsTemplate();
createJmsTemplateReciever();
JmsMessageCreator jmsMessageCreator = new JmsMessageCreator() {
#Override
public Message createMessage(Session session) throws JMSException {
BytesMessage msg = session.createBytesMessage();
msg.writeBytes(sendmessage.toByteArray());
return msg;
}
};
MessageCreator messageCreator = new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
Message msg = jmsMessageCreator.createMessage(session);
msg.setJMSCorrelationID("2708");
return msg;
}
};
jmsTemplate.send(messageCreator);
System.out.println("Message sent... ");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
//But when i am calling this method, at receive call it gets blocked...
public void recieveMessage() {
try {
byteMessage = (BytesMessage) jmsTemplateReciever.receive();
try {
if (byteMessage != null) {
byte[] byteArr = new byte[(int) byteMessage.getBodyLength()];
for (int i = 0; i < (int) byteMessage.getBodyLength(); i++) {
byteArr[i] = byteMessage.readByte();
String s = new String(byteArr);
System.out.println(s);
}
String s = new String(byteArr);
System.out.println(s);
byteMessage.acknowledge();
}
} catch (JMSException e) {
}
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
}
As described in section 9.2.2 of JMS 1.1 Specification, the receive() call blocks indefinitely until a message arrives on the queue. Hence the call is getting blocked in your application.
One option for you is to specify a wait time, for example receive(3000) which waits for 3 seconds and comes out if no message arrives in 3 seconds. JMS implementer might be providing another form of receive method where the method returns immediately if there are no messages in the queue.
The other option is to use a message listener for receiving messages asynchronously as described JMS 1.1 Specifications section 9.3.1. Your application gets notified by the JMS provider whenever a message arrives in a queue.

Adobe CQ : Regarding Session in Event Listener

I have a question regarding event listener. We have a event listener which listen to delete node event and perform some activity say "send email".
While code review i found this, although this code is working fine i am not convinced with the session being handled here :
#Activate
protected void activate(ComponentContext context) {
try{
final String path="/content/dam/";
Session session = repository.loginAdministrative(repository.getDefaultWorkspace());
observationManager = session.getWorkspace().getObservationManager();
observationManager.addEventListener(this, Event.PROPERTY_REMOVED, path, true, null, null, true);
checkOutProperty = OsgiUtil.toString(context.getProperties()
.get(ASSET_LOCK_PROPNAME_UPDATE), ASSET_LOCK_PROPNAME_DEFAULT);
if (session != null && session.isLive()) {
session.save();
}
} catch (RepositoryException e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured in activate method of Property Removed Listener class:" + e.getMessage());
}
}catch (Exception e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured in activate method of Property Removed Listener class:"+e.getMessage());
}
}
}
#Deactivate
protected void deactivate(ComponentContext componentContext) {
try {
if (observationManager != null) {
observationManager.removeEventListener(this);
}
} catch (RepositoryException e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured " + e);
}
} catch (Exception e) {
if(LOG.isErrorEnabled()){
LOG.error(e.getMessage());
}
}
}
Questions:
Best practice would be to create session object private to this class and should be logout in deactivate method?
Once an event is added in Observation Manager, do we really need session object? I was expecting if we should logout from session there.
EventListener are a bit cumbersome here. I fought many battles with JCR Sessions and Sling ResourceResolvers within them. The problem is, you need to keep the Session active as long as the Event Listener is active. So the only thing missing in your code is a logout on deactivate.
I created an AbstractEventListener which takes care of this and provides the following two methods and has two private members:
private Session session;
private ObservationManager observationManager;
protected void addEventListener(final EventListener eventListener,
final int eventTypes, final String path, final String[] nodeTypes) {
try {
session = getRepositorySession();
observationManager = session.getWorkspace().getObservationManager();
observationManager.addEventListener(eventListener, eventTypes,
path, true, null, nodeTypes, true);
} catch (RepositoryException e) {
LOGGER.error("Repository error while registering observation: ", e);
}
}
protected void removeEventListener(final EventListener eventListener) {
if (observationManager != null) {
try {
observationManager.removeEventListener(eventListener);
} catch (RepositoryException e) {
LOGGER.error(
"Repository error while unregistering observation: ", e);
} finally {
logoutSession(session);
}
}
}
And then in the actual EventListener I just call them:
protected void activate(ComponentContext context) {
addEventListener(this, Event.PROPERTY_ADDED| Event.PROPERTY_CHANGED, "/content/mysite", null);
}
}
protected void deactivate(ComponentContext componentContext) {
removeEventListener(this);
}

Resources