How to display local queues where curdepth reached its maxdepth in ibm mq - ibm-mq

I want to display all local queues where curdepth reached its maxdepth.
I understand that the below where condition in runmqsc will not work.
DIS QL(*) WHERE(CURDEPTH EQ MAXDEPTH)
I am trying to parse it with sed and awk but not even close as I am no expert in scripting
Please help in getting desired output. Thanks

Isn't this like trying to squeeze a fully blown up balloon into a wine bottle?
It would seem far, far simpler to just run a Java/MQ/PCF application to get both the current and maximum depths and compare the values.
Here is a simple (complete) Java/MQ/PCF application to do that:
Note: It has a filter on the PCF command to only return queues with a current depth greater than zero. Hence, the queue manager's command server will return less data and make over all processing faster.
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import com.ibm.mq.MQException;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.constants.CMQCFC;
import com.ibm.mq.headers.MQDataException;
import com.ibm.mq.headers.pcf.PCFMessage;
import com.ibm.mq.headers.pcf.PCFMessageAgent;
/**
* Program Name
* MQCurrentDepthMonitor01
*
* Description
* This java class issues a PCF "inquire queue" request message for all ("*") local queues
* with a queue depth greater than 0 (zero) of a remote queue manager and
* (1) output an error message if current depth is the same as max depth or
* (2) output a warning message if current depth is within 90% of max depth.
*
* Sample Command Line Parameters
* -m MQA1 -h 127.0.0.1 -p 1414 -c TEST.CHL -u UserID -x Password
*
* #author Roger Lacroix
*/
public class MQCurrentDepthMonitor01
{
private static final SimpleDateFormat LOGGER_TIMESTAMP = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
private Hashtable<String,String> params;
private Hashtable<String,Object> mqht;
private String qMgrName;
public MQCurrentDepthMonitor01()
{
super();
params = new Hashtable<String,String>();
mqht = new Hashtable<String,Object>();
}
/**
* 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("-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 HashTable.
* #param args
* #throws IllegalArgumentException
*/
private void init(String[] args) throws IllegalArgumentException
{
int port = 1414;
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())
{
qMgrName = (String) params.get("-m");
try
{
port = Integer.parseInt((String) params.get("-p"));
}
catch (NumberFormatException e)
{
port = 1414;
}
mqht.put(CMQC.CHANNEL_PROPERTY, params.get("-c"));
mqht.put(CMQC.HOST_NAME_PROPERTY, params.get("-h"));
mqht.put(CMQC.PORT_PROPERTY, new Integer(port));
mqht.put(CMQC.USER_ID_PROPERTY, params.get("-u"));
mqht.put(CMQC.PASSWORD_PROPERTY, params.get("-x"));
// I don't want to see MQ exceptions at the console.
MQException.log = null;
}
else
{
throw new IllegalArgumentException();
}
}
/**
* Handle connecting to the queue manager, issuing PCF command then
* looping through PCF response messages and disconnecting from
* the queue manager.
*/
private void doPCF()
{
MQQueueManager qMgr = null;
PCFMessageAgent agent = null;
PCFMessage request = null;
PCFMessage[] responses = null;
try
{
qMgr = new MQQueueManager(qMgrName, mqht);
MQCurrentDepthMonitor01.logger("successfully connected to "+ qMgrName);
agent = new PCFMessageAgent(qMgr);
MQCurrentDepthMonitor01.logger("successfully created agent");
// https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.1.0/com.ibm.mq.ref.adm.doc/q087800_.htm
request = new PCFMessage(CMQCFC.MQCMD_INQUIRE_Q);
/**
* You can explicitly set a queue name like "TEST.Q1" or
* use a wild card like "TEST.*"
*/
request.addParameter(CMQC.MQCA_Q_NAME, "*");
// Add parameter to request only local queues
request.addParameter(CMQC.MQIA_Q_TYPE, CMQC.MQQT_LOCAL);
// Add parameter to request only queue name, current depth and max depth
request.addParameter(CMQCFC.MQIACF_Q_ATTRS, new int [] {
CMQC.MQCA_Q_NAME,
CMQC.MQIA_CURRENT_Q_DEPTH,
CMQC.MQIA_MAX_Q_DEPTH
});
// Add filter to only return responses with a queue depth greater than 0 (zero)
// i.e. non-zero queue depth
request.addFilterParameter(CMQC.MQIA_CURRENT_Q_DEPTH, CMQCFC.MQCFOP_GREATER, 0);
responses = agent.send(request);
// MQCurrentDepthMonitor01.logger("responses.length="+responses.length);
int curDepth = -1;
int maxDepth = -1;
for (int i = 0; i < responses.length; i++)
{
if ( ((responses[i]).getCompCode() == CMQC.MQCC_OK) &&
((responses[i]).getParameterValue(CMQC.MQCA_Q_NAME) != null) )
{
String name = responses[i].getStringParameterValue(CMQC.MQCA_Q_NAME);
if (name != null)
name = name.trim();
curDepth = responses[i].getIntParameterValue(CMQC.MQIA_CURRENT_Q_DEPTH);
maxDepth = responses[i].getIntParameterValue(CMQC.MQIA_MAX_Q_DEPTH);
// MQCurrentDepthMonitor01.logger("Name="+name + " : curDepth="+curDepth + " : maxDepth="+maxDepth);
if (curDepth == maxDepth)
MQCurrentDepthMonitor01.logger("ERROR: Name="+name + " : current depth equals max depth ["+maxDepth+"]");
else if (curDepth >= (maxDepth * 0.9))
MQCurrentDepthMonitor01.logger("Warning: Name="+name + " : current depth ["+curDepth+"] is within 90% of max depth ["+maxDepth+"]");
}
}
}
catch (MQException e)
{
MQCurrentDepthMonitor01.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
catch (IOException e)
{
MQCurrentDepthMonitor01.logger("IOException:" +e.getLocalizedMessage());
}
catch (MQDataException e)
{
MQCurrentDepthMonitor01.logger("MQDataException:" +e.getLocalizedMessage());
}
finally
{
try
{
if (agent != null)
{
agent.disconnect();
MQCurrentDepthMonitor01.logger("disconnected from agent");
}
}
catch (MQDataException e)
{
MQCurrentDepthMonitor01.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
try
{
if (qMgr != null)
{
qMgr.disconnect();
MQCurrentDepthMonitor01.logger("disconnected from "+ qMgrName);
}
}
catch (MQException e)
{
MQCurrentDepthMonitor01.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
}
}
/**
* 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);
}
public static void main(String[] args)
{
MQCurrentDepthMonitor01 mqlqs = new MQCurrentDepthMonitor01();
try
{
mqlqs.init(args);
mqlqs.doPCF();
}
catch (IllegalArgumentException e)
{
MQCurrentDepthMonitor01.logger("Usage: java MQCurrentDepthMonitor01 -m QueueManagerName -h host -p port -c channel -u UserID -x Password");
System.exit(1);
}
System.exit(0);
}
}

Related

How to set MQ headers using JSR223 sampler in Jmeter

I am working on IBM MQ testing. I able to inject my payloads request in MQ destination. I need to put the headers values in MQ to get the correct response. I used various option but still i am unable to put headers values in MQ server. Kindly let me know how can i solve this in JMeter.
Option 1 :
sendmsg = new MQMessage();
sendmsg.setStringProperty("QueryName", "GetPortfolio");
sendmsg.setStringProperty("Country", "LV");
Option 2:
rfh2.setFieldValue('usr', 'QueryName=', 'GetPortfolio')
Option 3:
SampleResult.setRequestHeaders("QueryName=GetPortfolio")
Option # 1 is the correct way of doing it.
Option # 2 could be used but why? And the parameter should not include the equals sign ( i.e. "=").
I have no idea what option # 3 is.
Here is a sample Java/MQ program that puts a message on a queue with named properties .
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
/**
* Program Name
* MQTest11P
*
* Description
* This java class will connect to a remote queue manager with the
* MQ setting stored in a HashTable and put a message on 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 MQTest11P
{
private static final SimpleDateFormat LOGGER_TIMESTAMP = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
private Hashtable<String,String> params;
private Hashtable<String,Object> mqht;
private String qMgrName;
private String outputQName;
/**
* The constructor
*/
public MQTest11P()
{
super();
params = new Hashtable<String,String>();
mqht = new Hashtable<String,Object>();
}
/**
* 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 HashTable.
* #param args
* #throws IllegalArgumentException
*/
private void init(String[] args) throws IllegalArgumentException
{
int port = 1414;
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())
{
qMgrName = (String) params.get("-m");
outputQName = (String) params.get("-q");
try
{
port = Integer.parseInt((String) params.get("-p"));
}
catch (NumberFormatException e)
{
port = 1414;
}
mqht.put(CMQC.CHANNEL_PROPERTY, params.get("-c"));
mqht.put(CMQC.HOST_NAME_PROPERTY, params.get("-h"));
mqht.put(CMQC.PORT_PROPERTY, new Integer(port));
mqht.put(CMQC.USER_ID_PROPERTY, params.get("-u"));
mqht.put(CMQC.PASSWORD_PROPERTY, params.get("-x"));
// I don't want to see MQ exceptions at the console.
MQException.log = null;
}
else
{
throw new IllegalArgumentException();
}
}
/**
* Connect, open queue, write a message, close queue and disconnect.
*
*/
private void testSend()
{
MQQueueManager qMgr = null;
MQQueue queue = null;
String msgData = "This is a test message from MQTest11P";
int openOptions = CMQC.MQOO_OUTPUT + CMQC.MQOO_FAIL_IF_QUIESCING;
MQPutMessageOptions pmo = new MQPutMessageOptions();
try
{
qMgr = new MQQueueManager(qMgrName, mqht);
MQTest11P.logger("successfully connected to "+ qMgrName);
queue = qMgr.accessQueue(outputQName, openOptions);
MQTest11P.logger("successfully opened "+ outputQName);
// Define a simple MQ message, and write some text
MQMessage sendmsg = new MQMessage();
sendmsg.format = CMQC.MQFMT_STRING;
sendmsg.feedback = CMQC.MQFB_NONE;
sendmsg.messageType = CMQC.MQMT_DATAGRAM;
sendmsg.messageId = CMQC.MQMI_NONE;
sendmsg.correlationId = CMQC.MQCI_NONE;
// Write message data
sendmsg.writeString(msgData);
/**
* Set named properties aka message properties
* that will create a JMS message.
*/
// sendmsg.setStringProperty("mcd.Msd", "jms_text");
// sendmsg.setStringProperty("jms.Dst", "queue:///"+outputQName);
// sendmsg.setStringProperty("jms.Pri", "0");
sendmsg.setStringProperty("QueryName", "GetPortfolio");
sendmsg.setStringProperty("Country", "LV");
// put the message on the queue
queue.put(sendmsg, pmo);
MQTest11P.logger("Message Data>>>" + msgData);
}
catch (MQException e)
{
MQTest11P.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
catch (IOException e)
{
MQTest11P.logger("IOException:" +e.getLocalizedMessage());
}
finally
{
try
{
if (queue != null)
{
queue.close();
MQTest11P.logger("closed: "+ outputQName);
}
}
catch (MQException e)
{
MQTest11P.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
try
{
if (qMgr != null)
{
qMgr.disconnect();
MQTest11P.logger("disconnected from "+ qMgrName);
}
}
catch (MQException e)
{
MQTest11P.logger("CC=" +e.completionCode + " : RC=" + e.reasonCode);
}
}
}
/**
* 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);
}
/**
* main line
* #param args
*/
public static void main(String[] args)
{
MQTest11P write = new MQTest11P();
try
{
write.init(args);
write.testSend();
}
catch (IllegalArgumentException e)
{
MQTest11P.logger("Usage: java MQTest11P -m QueueManagerName -h host -p port -c channel -q QueueName -u UserID -x Password");
System.exit(1);
}
System.exit(0);
}
}
When I look at the message in the queue with MQ Visual Edit, I see:
So, your 2 named properties are with the message.
The question becomes do you want JUST named properties attached to the message or are you really looking to create a JMS message with named properties?
Note: A JMS message is internally defined as an MQRFH2 message. i.e. JMS message ==> MQRFH2 message but the opposite may not be true.
Hence, if you want a JMS message with named properties then you need to uncomment those 3 lines in MQTest11P.java above.
i.e.
sendmsg.setStringProperty("mcd.Msd", "jms_text");
sendmsg.setStringProperty("jms.Dst", "queue:///"+outputQName);
sendmsg.setStringProperty("jms.Pri", "0");

Sms not receiving from java web application

I have written java code which is used to send sms using sms gateway. JAVA OpenSMPP API is used to implement the logic for sending SMPP request. I have needed below information which is used to connect to the sms gateway and which is used to send sms :
SMS_GATEWAY_USERNAME 906o2portt02
SMS_GATEWAY_PORT 9205 S
SMS_GATEWAY_IP_2 34.22.91.166
SMS_GATEWAY_IP_1 80.77.67.145
I am able to send sms but i dont understand for what reason i am not receiving sms. I have also put the debug statement in my code to check for any error. When i checked the log file i am getting below information which says sms has been send. Previously I had different port number,username and password and i was able to send and recieve sms using the same java code. But now i have the requirement to send sms on this gateway and its also sending an sms. but for some reason i am not receiving sms. Is there any way to check what happened to my sms which has been send ?
Below is my code :
public class SMSClient
{
private static final Logger logger = LoggerFactory
.getLogger(SMSClient.class);
#Autowired
private SMSSettings smsSettings;
#Autowired
private OracleSettings oracleSettings;
/**
* If the application is bound to the SMSC.
*/
boolean _bound = false;
public boolean send(String text,
List<AlertCommunicationAddress> toAddressesSMS)
{
List<String> toAddressesSMSString = new ArrayList<String>();
for (AlertCommunicationAddress alertComAddr : toAddressesSMS)
{
List<AlertRecpGrpMember> recpMembers = alertComAddr
.getAlertRecipientsGroup().getAlertRecpGrpMembers();
for (AlertRecpGrpMember recpMem : recpMembers)
{
// check here if the member belongs to the same environment on
// which SMS is being sent.
if ((recpMem.getIsDefault() != null && recpMem.getIsDefault()
.equalsIgnoreCase("Y"))
|| (recpMem.getRunEnvironment() != null && recpMem
.getRunEnvironment().equalsIgnoreCase(
oracleSettings.getRunEnv())))
{
toAddressesSMSString.add(recpMem.getMember());
}
}
}
logger.debug("Original SMS to be sent : " + text);
String smscHost1 = smsSettings.getHost1();
Integer smscPort = smsSettings.getPort();
if (toAddressesSMSString.isEmpty())
{
return false;
}
for (String phoneNumber : toAddressesSMSString)
{
try
{
Session session = getSession(smscHost1, smscPort,
smsSettings.getUsername(), smsSettings.getPassword());
if (session == null)
{
String smscHost2 = smsSettings.getHost2();
logger.error("SMS --- Unable to get the session with Host 1 (" + smscHost1 + ":" + smscPort + ") , will try Host 2 (" + smscHost2 + ") now.");
session = getSession(smscHost2, smscPort,
smsSettings.getUsername(),
smsSettings.getPassword());
if (session == null)
{
logger.error("SMS --- Unable to get the session with Host 1 (" + smscHost1 + ") and Host 2 (" + smscHost2 + "). Please check with the SMS Gateway.");
return false;
}
}
logger.debug("SMS --- Created Session object " + session);
SubmitSM request = new SubmitSM();
request.setSourceAddr(new Address((byte) 5, (byte) 0,
"RM2Support"));
request.setDestAddr(createAddress(phoneNumber));
request.setProtocolId((byte) 0);
request.setPriorityFlag((byte) 0);
request.setRegisteredDelivery((byte) 1); // we want delivery
// reports
request.setDataCoding((byte) 0);
request.setSmDefaultMsgId((byte) 0);
// request.setScheduleDeliveryTime(deliveryTime); // you can
// skip
// this
request.setReplaceIfPresentFlag((byte) 0);
// Send the request
request.assignSequenceNumber(true);
// this is to send long messages
request.setEsmClass((byte) Data.SM_UDH_GSM);
String[] splittedMsg = splitMessage(text, 153);
int totalSegments = splittedMsg.length;
logger.debug("SMS : Number of splitted segments :: "
+ totalSegments);
// iterating on splittedMsg array. Only Sequence Number and
// short
// message text will change each time
Random random = new Random();
int randomInt = random.nextInt();
logger.debug("SMS---- Reference Number : " + randomInt);
for (int i = 0; i < totalSegments; i++)
{
ByteBuffer ed = new ByteBuffer();
ed.appendByte((byte) 5); // UDH Length
ed.appendByte((byte) 0x00); // IE Identifier
ed.appendByte((byte) 3); // IE Data Length
ed.appendByte((byte) randomInt); // Reference Number
ed.appendByte((byte) totalSegments); // Number of pieces
ed.appendByte((byte) (i + 1)); // Sequence number
ed.appendString(splittedMsg[i], Data.ENC_ASCII);
request.setShortMessageData(ed);
logger.debug("Hello...reached here...now about the submit the request::::");
SubmitSMResp response = session.submit(request);
logger.debug("SMS --- Submit response "
+ response.getCommandStatus());
// response = smsSession.submitMulti(request);
logger.debug("SMS --- Submit response "
+ response.getCommandStatus());
String messageId = response.getMessageId();
logger.debug("SMS --- Message ID = " + messageId);
}
enquireLink(session);
unbind(session);
} catch (Exception e)
{
logger.debug("Exception while sending SMS with Phone number :::" + phoneNumber + "::::" + e);
continue;
}
}
return true;
}
private Session getSession(String smscHost, int smscPort,
String smscUsername, String smscPassword) throws Exception
{
try
{
TCPIPConnection connection = new TCPIPConnection(smscHost, smscPort);
connection.setReceiveTimeout(6000);
connection.setIOBufferSize(8188);
connection.setReceiveBufferSize(8188);
Session session = new Session(connection);
// bind now
if (_bound)
{
logger.debug("Already bound, unbind first.");
return session;
}
BindRequest request = new BindTransmitter();
request.setSystemId(smscUsername);
request.setPassword(smscPassword);
// request.setSystemType(systemType);
// request.setAddressRange(addressRange);
request.setInterfaceVersion((byte) 0x34); // SMPP protocol version
logger.debug("SMS --- Bind request :: " + request.debugString());
logger.debug("SMS --- Created Session object :: " + session);
BindResponse response = session.bind(request);
logger.debug("Bind response " + response.debugString());
if (response.getCommandStatus() == Data.ESME_ROK)
{
logger.debug("SMS --- Binded with SMSC Server");
_bound = true;
} else
{
logger.error("SMS --- Unable to bind with SMSC Server :: Code :: "
+ response.getCommandStatus());
}
Integer respCode = new Integer(response.getCommandStatus());
logger.debug("SMS -- Response Code ::" + respCode);
response.setCommandStatus(respCode);
Integer comLength = new Integer(response.getCommandLength());
logger.debug("SMS -- CommandLength ::" + comLength);
response.setCommandLength(comLength);
logger.debug("SMS --- Response from SMSC" + response.toString());
return session;
} catch (WrongLengthOfStringException e)
{
logger.error("SMS -- Wrong length string exception"
+ e.getMessage());
} catch (ValueNotSetException e)
{
logger.error("SMS -- Value not set exception" + e.getMessage());
} catch (TimeoutException e)
{
logger.error("SMS -- Timeout exception " + e.getMessage());
} catch (PDUException e)
{
logger.error("SMS -- PDU exception " + e.getMessage());
} catch (WrongSessionStateException e)
{
logger.error("SMS -- Wrong Session exception " + e.getMessage());
} catch (IOException e)
{
logger.error("SMS --- Could not able to connect the host/port or Check the Username/Password for connection ::"
+ e.getMessage());
} catch (Exception e)
{
logger.error("SMS -- Error while sending SMS :: " + e.getMessage());
}
return null;
}
private Address createAddress(String address)
throws WrongLengthOfStringException
{
Address addressInst = new Address();
addressInst.setTon((byte) 5); // national ton
addressInst.setNpi((byte) 0); // numeric plan indicator
addressInst.setAddress(address, Data.SM_ADDR_LEN);
logger.debug("SMS -------- Address :: " + addressInst);
return addressInst;
}
private Session unbind(Session session)
{
try
{
if (!_bound)
{
System.out.println("Not bound, cannot unbind.");
return session;
}
// send the request
logger.debug("Going to unbind.");
if (session.getReceiver().isReceiver())
{
logger.debug("SMS --- Unbinding --- It can take a while to stop the receiver.");
}
UnbindResp response = session.unbind();
logger.debug("Unbind response " + response.debugString());
_bound = false;
} catch (Exception e)
{
logger.debug("Unbind operation failed. " + e);
}
return session;
}
/**
* Creates a new instance of <code>EnquireSM</code> class. This PDU is used
* to check that application level of the other party is alive. It can be
* sent both by SMSC and ESME.
*
* See "SMPP Protocol Specification 3.4, 4.11 ENQUIRE_LINK Operation."
*
* #see Session#enquireLink(EnquireLink)
* #see EnquireLink
* #see EnquireLinkResp
*/
private void enquireLink(Session session)
{
try
{
EnquireLink request = new EnquireLink();
EnquireLinkResp response;
logger.debug("SMS ---- Enquire Link request "
+ request.debugString());
response = session.enquireLink(request);
logger.debug("SMS --- Enquire Link response "
+ response.debugString());
} catch (Exception e)
{
logger.debug("SMS ---- Enquire Link operation failed :: " + e);
}
}
private String[] splitMessage(String s, int size)
{
if (s == null || size <= 0)
return null;
int chunks = s.length() / size + ((s.length() % size > 0) ? 1 : 0);
String[] arr = new String[chunks];
for (int i = 0, j = 0, l = s.length(); i < l; i += size, j++)
arr[j] = s.substring(i, Math.min(l, i + size));
return arr;
}
}
Below is the parameter i need to consider while send/receive sms. But i really dont know whetherJAVA OpenSMPP APIuses this settings:
You can use the following code to query SMPP server to check what happend to you message (from https://github.com/OpenSmpp/opensmpp/blob/master/client/src/main/java/org/smpp/test/SMPPTest.java):
/**
* Creates a new instance of <code>QuerySM</code> class, lets you set
* subset of fields of it. This PDU is used to fetch information
* about status of already submitted message providing that you 'remember'
* message id of the submitted message. The message id is assigned
* by SMSC and is returned to you with the response to the submision
* PDU (SubmitSM, DataSM etc.).
*
* See "SMPP Protocol Specification 3.4, 4.8 QUERY_SM Operation."
* #see Session#query(QuerySM)
* #see QuerySM
* #see QuerySMResp
*/
private void query() {
debug.enter(this, "SMPPTest.query()");
try {
QuerySM request = new QuerySM();
QuerySMResp response;
// input values
messageId = getParam("Message id", messageId);
sourceAddress = getAddress("Source", sourceAddress);
// set values
request.setMessageId(messageId);
request.setSourceAddr(sourceAddress);
// send the request
System.out.println("Query request " + request.debugString());
if (asynchronous) {
session.query(request);
} else {
response = session.query(request);
System.out.println("Query response " + response.debugString());
messageId = response.getMessageId();
}
} catch (Exception e) {
event.write(e, "");
debug.write("Query operation failed. " + e);
System.out.println("Query operation failed. " + e);
} finally {
debug.exit(this);
}
}

How could i cache OCSP response with iTextSharp (LTV signature)?

I'm using iTextSharp 5.5.10 in order to generate signed PDF. In particular, i need LTV signature. LTV can be done with CRL and OCSP requests.
I did it with such a code :
IOcspClient ocspClient = new OcspClientBouncyCastle();
ICrlClient crlClient = new CrlClientOnline(myCert.Chain);
List<ICrlClient> lstCrlClients = new List<ICrlClient> { crlClient };
MakeSignature.SignDetached(sap, signature, this.myCert.Chain, lstCrlClients, ocspClient, null, 0, CryptoStandard.CMS);
The problem is : i'm signing many, many PDF (always with the same certificate). So, i don't want to make CRL and OCSP request each time, i have to "cache" them.
I managed to cache the CRL with this kind of code (it relies on C# MemoryCache) :
private List<ICrlClient> GetCachedListCrlClient()
{
var key = "LstCrlClient";
List<ICrlClient> lstCrlClients = MyGlobalCachingProvider.GetItem<List<ICrlClient>>(key);
if (lstCrlClients == null)
{
lstCrlClients = new List<ICrlClient>();
for (int i = 0; i < myCert.Chain.Length; i++)
{
String crlUrl = CertificateUtil.GetCRLURL(myCert.Chain[i]);
if (crlUrl != null)
{
byte[] crlDownloaded = new System.Net.WebClient().DownloadData(crlUrl);
ICrlClient crlClient = new CrlClientOffline(crlDownloaded);
lstCrlClients.Add(crlClient);
}
}
MyGlobalCachingProvider.AddItem(key, lstCrlClients, DateTime.Now.AddHours(2));
}
return lstCrlClients;
}
I can't find however any solution to cache OCSP responses. Does anybody have a clue ?
Thanks to mlk comment, i did it : i have implemented my own class, inspired by OcspClientBouncyCastle code. The code is, indeed, trivial. My class manage caching : it sends only one OCSP request. This is the good way to do the stuff.
Sample code :
// Once instanciated, this class fires one and only one OCSP request : it keeps the first result in memory.
// You may want to cache this object ; ie with MemoryCache.
public class MyOcspClientBouncyCastleSingleRequest : IOcspClient
{
private static readonly ILogger LOGGER = LoggerFactory.GetLogger(typeof(OcspClientBouncyCastle));
private readonly OcspVerifier verifier;
// The request-result
private Dictionary<String, BasicOcspResp> _cachedOcspResponse = new Dictionary<string, BasicOcspResp>();
/**
* Create default implemention of {#code OcspClient}.
* Note, if you use this constructor, OCSP response will not be verified.
*/
[Obsolete]
public MyOcspClientBouncyCastleSingleRequest()
{
verifier = null;
}
/**
* Create {#code OcspClient}
* #param verifier will be used for response verification. {#see OCSPVerifier}.
*/
public MyOcspClientBouncyCastleSingleRequest(OcspVerifier verifier)
{
this.verifier = verifier;
}
/**
* Gets OCSP response. If {#see OCSPVerifier} was set, the response will be checked.
*/
public virtual BasicOcspResp GetBasicOCSPResp(X509Certificate checkCert, X509Certificate rootCert, String url)
{
String dicKey = checkCert.SubjectDN.ToString() + "-" + rootCert.SubjectDN.ToString() + "-" + url;
if (_cachedOcspResponse != null && _cachedOcspResponse.Count > 0 && _cachedOcspResponse.ContainsKey(dicKey))
{
BasicOcspResp cachedResult = _cachedOcspResponse[dicKey];
return cachedResult;
}
else
{
try
{
OcspResp ocspResponse = GetOcspResponse(checkCert, rootCert, url);
if (ocspResponse == null)
{
_cachedOcspResponse.Add(dicKey, null);
return null;
}
if (ocspResponse.Status != OcspRespStatus.Successful)
{
_cachedOcspResponse.Add(dicKey, null);
return null;
}
BasicOcspResp basicResponse = (BasicOcspResp)ocspResponse.GetResponseObject();
if (verifier != null)
{
verifier.IsValidResponse(basicResponse, rootCert);
}
_cachedOcspResponse.Add(dicKey, basicResponse);
return basicResponse;
}
catch (Exception ex)
{
if (LOGGER.IsLogging(Level.ERROR))
LOGGER.Error(ex.Message);
}
return null;
}
}
/**
* Gets an encoded byte array with OCSP validation. The method should not throw an exception.
*
* #param checkCert to certificate to check
* #param rootCert the parent certificate
* #param url to get the verification. It it's null it will be taken
* from the check cert or from other implementation specific source
* #return a byte array with the validation or null if the validation could not be obtained
*/
public byte[] GetEncoded(X509Certificate checkCert, X509Certificate rootCert, String url)
{
try
{
BasicOcspResp basicResponse = GetBasicOCSPResp(checkCert, rootCert, url);
if (basicResponse != null)
{
SingleResp[] responses = basicResponse.Responses;
if (responses.Length == 1)
{
SingleResp resp = responses[0];
Object status = resp.GetCertStatus();
if (status == CertificateStatus.Good)
{
return basicResponse.GetEncoded();
}
else if (status is RevokedStatus)
{
throw new IOException(MessageLocalization.GetComposedMessage("ocsp.status.is.revoked"));
}
else
{
throw new IOException(MessageLocalization.GetComposedMessage("ocsp.status.is.unknown"));
}
}
}
}
catch (Exception ex)
{
if (LOGGER.IsLogging(Level.ERROR))
LOGGER.Error(ex.Message);
}
return null;
}
/**
* Generates an OCSP request using BouncyCastle.
* #param issuerCert certificate of the issues
* #param serialNumber serial number
* #return an OCSP request
* #throws OCSPException
* #throws IOException
*/
private static OcspReq GenerateOCSPRequest(X509Certificate issuerCert, BigInteger serialNumber)
{
// Generate the id for the certificate we are looking for
CertificateID id = new CertificateID(CertificateID.HashSha1, issuerCert, serialNumber);
// basic request generation with nonce
OcspReqGenerator gen = new OcspReqGenerator();
gen.AddRequest(id);
// create details for nonce extension
IDictionary extensions = new Hashtable();
extensions[OcspObjectIdentifiers.PkixOcspNonce] = new X509Extension(false, new DerOctetString(new DerOctetString(PdfEncryption.CreateDocumentId()).GetEncoded()));
gen.SetRequestExtensions(new X509Extensions(extensions));
return gen.Generate();
}
private OcspResp GetOcspResponse(X509Certificate checkCert, X509Certificate rootCert, String url)
{
if (checkCert == null || rootCert == null)
return null;
if (url == null)
{
url = CertificateUtil.GetOCSPURL(checkCert);
}
if (url == null)
return null;
LOGGER.Info("Getting OCSP from " + url);
OcspReq request = GenerateOCSPRequest(rootCert, checkCert.SerialNumber);
byte[] array = request.GetEncoded();
HttpWebRequest con = (HttpWebRequest)WebRequest.Create(url);
con.ContentLength = array.Length;
con.ContentType = "application/ocsp-request";
con.Accept = "application/ocsp-response";
con.Method = "POST";
Stream outp = con.GetRequestStream();
outp.Write(array, 0, array.Length);
outp.Close();
HttpWebResponse response = (HttpWebResponse)con.GetResponse();
if (response.StatusCode != HttpStatusCode.OK)
throw new IOException(MessageLocalization.GetComposedMessage("invalid.http.response.1", (int)response.StatusCode));
Stream inp = response.GetResponseStream();
OcspResp ocspResponse = new OcspResp(inp);
inp.Close();
response.Close();
return ocspResponse;
}

JeroMQ: connection does not recover reliably

I have two applications, sending messages asynchronously in both directions. I am using sockets of type ZMQ.DEALER on both sides. The connection status is additionally controlled by heartbeating.
I have now problems to get the connection reliably recovering after connection problems (line failure or application restart on one side). When I restart the applicaton on the server side (the side doing the bind()), the client side will not always reconnect successfully and then needs to be restarted, especially when the local buffer has reached the HWM limit.
I did not find any other way to make the connection recovery reliable, other than resetting the complete ZMQ.Context in case of heartbeat failures or if send() returned false. I will then call Context.term() and will create Context and Socket again. This seemed to work fine in my tests. But now I observed occasional and hangups inside Context.term(), which are rare and hard to reproduce. I know, that creating the Context should be done just once at application startup, but as said I found no other way to re-establish a broken connection.
I am using JeroMQ 0.3.4. The source of a test application is below, ~200 lines of code.
Any hints to solve this are very much appreciated.
import java.util.Calendar;
import org.zeromq.ZMQ;
public class JeroMQTest {
public interface IMsgListener {
public void newMsg(byte[] message);
}
final static int delay = 100;
final static boolean doResetContext = true;
static JeroMQTest jeroMQTest;
static boolean isServer;
private ZMQ.Context zContext;
private ZMQ.Socket zSocket;
private String address = "tcp://localhost:9889";
private long lastHeartbeatReceived = 0;
private long lastHeartbeatReplyReceived;
private boolean sendStat = true, serverIsActive = false, receiverInterrupted = false;
private Thread receiverThread;
private IMsgListener msgListener;
public static void main(String[] args) {
isServer = args.length > 0 && args[0].equals("true");
if (isServer) {
new JeroMQTest().runServer();
}
else {
new JeroMQTest().runClient();
}
}
public void runServer() {
msgListener = new IMsgListener() {
public void newMsg(byte[] message) {
String msgReceived = new String(message);
if (msgReceived.startsWith("HEARTBEAT")) {
String msgSent = "HEARTBEAT_REP " + msgReceived.substring(10);
sendStat = zSocket.send(msgSent.getBytes());
System.out.println("heartbeat rcvd, reply sent, status:" + sendStat);
lastHeartbeatReceived = getNow();
} else {
System.out.println("msg received:" + msgReceived);
}
}
};
createJmq();
sleep(1000);
int ct = 1;
while (true) {
boolean heartbeatsOk = lastHeartbeatReceived > getNow() - delay * 4;
if (heartbeatsOk) {
serverIsActive = true;
String msg = "SERVER " + ct;
sendStat = zSocket.send(msg.getBytes());
System.out.println("msg sent:" + msg + ", status:" + sendStat);
ct++;
}
if (serverIsActive && (!heartbeatsOk || !sendStat)) {
serverIsActive = false;
if (doResetContext) {
resetContext();
}
}
sleep(delay);
}
}
public void runClient() {
msgListener = new IMsgListener() {
public void newMsg(byte[] message) {
String msgReceived = new String(message);
if (msgReceived.startsWith("HEARTBEAT_REP")) {
System.out.println("HEARTBEAT_REP received:" + msgReceived);
lastHeartbeatReplyReceived = getNow();
}
else {
System.out.println("msg received:" + msgReceived);
}
}
};
createJmq();
sleep(1000);
int ct = 1;
boolean reconnectDone = false;
while (true) {
boolean heartbeatsOK = lastHeartbeatReplyReceived > getNow() - delay * 4;
String msg = "HEARTBEAT " + (ct++);
sendStat = zSocket.send(msg.getBytes());
System.out.println("heartbeat sent:" + msg + ", status:" + sendStat);
sleep(delay / 2);
if (sendStat) {
msg = "MSG " + ct;
sendStat = zSocket.send(msg.getBytes());
System.out.println("msg sent:" + msg + ", status:" + sendStat);
reconnectDone = false;
}
if ((!heartbeatsOK && lastHeartbeatReplyReceived > 0) || (!sendStat && !reconnectDone)) {
if (doResetContext) {
resetContext();
}
lastHeartbeatReplyReceived = 0;
reconnectDone = true;
}
sleep(delay / 2);
}
}
public void resetContext() {
closeJmq();
sleep(1000);
createJmq();
System.out.println("resetContext done");
}
private void createJmq() {
zContext = ZMQ.context(1);
zSocket = zContext.socket(ZMQ.DEALER);
zSocket.setSendTimeOut(100);
zSocket.setReceiveTimeOut(100);
zSocket.setSndHWM(10);
zSocket.setRcvHWM(10);
zSocket.setLinger(100);
if (isServer) {
zSocket.bind(address);
} else {
zSocket.connect(address);
}
receiverThread = new Thread() {
public void run() {
receiverInterrupted = false;
try {
ZMQ.Poller poller = new ZMQ.Poller(1);
poller.register(zSocket, ZMQ.Poller.POLLIN);
while (!receiverInterrupted) {
if (poller.poll(100) > 0) {
byte byteArr[] = zSocket.recv(0);
msgListener.newMsg(byteArr);
}
}
poller.unregister(zSocket);
} catch (Throwable e) {
System.out.println("Exception in ReceiverThread.run:" + e.getMessage());
}
}
};
receiverThread.start();
}
public void closeJmq() {
receiverInterrupted = true;
sleep(100);
zSocket.close();
zContext.term();
}
long getNow() {
Calendar now = Calendar.getInstance();
return (long) (now.getTime().getTime());
}
private static void sleep(int mSleep) {
try {
Thread.sleep(mSleep);
} catch (InterruptedException e) {
}
}
}

BlackBerry - Downloaded images are corrupted on wifi with HttpConnection

In my app I need to download several images from a server. I use this code to get a byte array :
HttpConnection connection = null;
InputStream inputStream = null;
byte[] data = null;
try
{
//connection = (HttpConnection)Connector.open(url);
connection = (HttpConnection)Connector.open(url, Connector.READ_WRITE, true);
int responseCode = connection.getResponseCode();
if(responseCode == HttpConnection.HTTP_OK)
{
inputStream = connection.openInputStream();
data = IOUtilities.streamToBytes(inputStream);
inputStream.close();
}
connection.close();
return data;
}
catch(IOException e)
{
return null;
}
The url are formed with the suffix ";deviceSide=false;ConnectionType=MDS - public" (without spaces) and it is working perfectly well.
The problem is that with phones that do not have a sim card, we can't connect to the internet via the MDS server. So we changed to use the connection factory and let BB choose whatever he wants :
ConnectionFactory connFact = new ConnectionFactory();
ConnectionDescriptor connDesc;
connDesc = connFact.getConnection(url);
if (connDesc != null)
{
final HttpConnection httpConn;
httpConn = (HttpConnection)connDesc.getConnection();
try
{
httpConn.setRequestMethod(HttpConnection.GET);
final int iResponseCode = httpConn.getResponseCode();
if(iResponseCode == HttpConnection.HTTP_OK)
{
InputStream inputStream = null;
try{
inputStream = httpConn.openInputStream();
byte[] data = IOUtilities.streamToBytes(inputStream);
return data;
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
finally{
try
{
inputStream.close();
} catch (IOException e)
{
e.printStackTrace();
return null;
}
}
}
}
catch (IOException e)
{
System.err.println("Caught IOException: " + e.getMessage());
}
}
return null;
The connection works because it select the good prefix (interface=wifi in our case), but this create another problem.
Some images are not well downloaded, some of them (not the sames at each try) are corrupted, but only when the phone use a wifi connection to get these images.
How can I avoid this problem ? What method to get a connection do I have to use ? Is it possible to check if the user have a sim card in orderto use MDS - public ?
Here is an example of a corrupted image :
error image http://nsa30.casimages.com/img/2012/06/28/120628033716123822.png
try this:
public static String buildURL(String url) {
String connParams = "";
if (WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED) {
connParams = ";interface=wifi"; //Connected to a WiFi access point.
} else {
int coverageStatus = CoverageInfo.getCoverageStatus();
//
if ((coverageStatus & CoverageInfo.COVERAGE_BIS_B) == CoverageInfo.COVERAGE_BIS_B) {
connParams = ";deviceside=false;ConnectionType=mds-public";
} else if ((coverageStatus & CoverageInfo.COVERAGE_DIRECT) == CoverageInfo.COVERAGE_DIRECT) {
// Have network coverage and a WAP 2.0 service book record
ServiceRecord record = getWAP2ServiceRecord();
//
if (record != null) {
connParams = ";deviceside=true;ConnectionUID=" + record.getUid();
} else {
connParams = ";deviceside=true";
}
} else if ((coverageStatus & CoverageInfo.COVERAGE_MDS) == CoverageInfo.COVERAGE_MDS) {
// Have an MDS service book and network coverage
connParams = ";deviceside=false";
}
}
Log.d("connection param"+url+connParams);
//
return url+connParams;
}
private static ServiceRecord getWAP2ServiceRecord() {
String cid;
String uid;
ServiceBook sb = ServiceBook.getSB();
ServiceRecord[] records = sb.getRecords();
//
for (int i = records.length -1; i >= 0; i--) {
cid = records[i].getCid().toLowerCase();
uid = records[i].getUid().toLowerCase();
//
if (cid.indexOf("wptcp") != -1
&& records[i].getUid().toLowerCase().indexOf("wap2") !=-1
&& uid.indexOf("wifi") == -1
&& uid.indexOf("mms") == -1) {
return records[i];
}
}
//
return null;
}
What happens when you append interface=wifi? Can you run the network diagnostic tool attached to below kb article and run all tests with SIM removed
http://supportforums.blackberry.com/t5/Java-Development/What-Is-Network-API-alternative-for-legacy-OS/ta-p/614822
Please also note that when download large files over BES/MDS there are limits imposed by MDS. Please ensure you review the below kb article
http://supportforums.blackberry.com/t5/Java-Development/Download-large-files-using-the-BlackBerry-Mobile-Data-System/ta-p/44585
You can check to see if coverage is sufficient for BIS_B (MDS public) but that won't help you if you are trying to support SIM-less users. I wonder if the problem is in an incomparability between the connection on Wi-Fi and IOUtilities.streamToBytes(). Try coding as recommended in the API documents.

Resources