I want to perform functional test of JPOS based ISO message and response(TPS) using Jmeter.Can anyone guide me on this?Do I need to install any plugin in Jmeter.As I have tried to install the Jmeter in my system.But Can't see any Jpos plugin in listeners to start with.Dev is Using Socket connection in Jpos.
I don't think you will be able to find any plugin, however you should be able to use jPOS client library from the JSR223 Sampler
Download the jPOS and build it using Gradle
Copy jpos/build/libs/jpos-x.x.x.jar to JMeter Classpath (along with dependencies, if you don't have them yet)
Restart JMeter to pick the library up
Add JSR223 Sampler to your Test Plan and put the code, implementing your test scenario into "Script" area, an example would be something like:
import org.jpos.iso.ISOMsg
import org.jpos.iso.channel.ASCIIChannel
import org.jpos.iso.packager.ISO87APackager
def host = 'your_host'
def port = 1234
def channel = new ASCIIChannel(host, port, new ISO87APackager())
channel.connect()
def message = new ISOMsg()
message.setMTI("0800")
message.set(3, "000000")
message.set(41, "00000001")
message.set(70, "301")
channel.send(message)
ISOMsg response = channel.receive()
channel.disconnect()
More information:
jPOS Programmer’s Guide
Apache Groovy - Why and How You Should Use It
We can send a XML or rawMessage to jpos server from the Jmeter TCPSampler
You can also add TPS listeners
enter image description here
And JPosTCPClient can be implemented
public class JPosTCPClient extends TCPClientImpl {
private static final Logger log = LoggingManager.getLoggerForClass();
private String containsString = "</isomsg>";
private boolean filterEnabled = true;
public JPosTCPClient() {
filterEnabled = Boolean.parseBoolean(JMeterUtils.getPropDefault("jpos.tcp.use", "true"));
containsString = JMeterUtils.getPropDefault("jpos.tcp.contains", "</isomsg>");
}
/**
* Reads data until the defined EOL byte is reached.
* If there is no EOL byte defined, then reads until
* the end of the stream is reached.
*/
#Override
public String read(InputStream is) {
byte[] buffer = new byte[4096];
ByteArrayOutputStream w = new ByteArrayOutputStream();
int x = 0;
boolean contains = false;
try {
while ((x = is.read(buffer)) > -1) {
w.write(buffer, 0, x);
if(filterEnabled){
String response = new String(buffer);
if(response.contains(containsString)){
contains = true;
break;
} else {
System.out.println("Contents: " + response);
}
}
}
if(filterEnabled && !contains){
System.out.println("Skipped containsString checking, x length:" + x);
}
} catch (SocketTimeoutException e) {
// drop out to handle buffer
System.out.println(e.getMessage());
} catch (InterruptedIOException e) {
// drop out to handle buffer
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
log.warn("Read error:" + e);
return "";
}
// do we need to close byte array (or flush it?)
log.debug("Read: " + w.size() + "\n" + w.toString());
return w.toString();
}
}
Related
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");
I am working on a legacy (Java 6/7) project that uses ProcessBuilder to request a UUID from the machine in an OS-agnostic way. I would like to use the Process.waitFor(long timeout, TimeUnit unit) method from Java 8, but this isn't implemented in Java 6. Instead, I can use waitFor(), which blocks until completion or an error.
I would like to avoid upgrading the version of Java used to 8 if possible as this necessitates a lot of other changes (migrating code away from removed internal APIs and upgrading a production Tomcat server, for example).
How can I best implement the code for executing the process, with a timeout? I was thinking of somehow implementing a schedule that checks if the process is still running and cancelling/destroying it if it is and the timeout has been reached.
My current (Java 8) code looks like this:
/** USE WMIC on Windows */
private static String getSystemProductUUID() {
String uuid = null;
String line;
List<String> cmd = new ArrayList<String>() {{
add("WMIC.exe"); add("csproduct"); add("get"); add("UUID");
}};
BufferedReader br = null;
Process p = null;
SimpleLogger.debug("Attempting to retrieve Windows System UUID through WMIC ...");
try {
ProcessBuilder pb = new ProcessBuilder().directory(getExecDir());
p = pb.command(cmd).start();
if (!p.waitFor(TIMEOUT, SECONDS)) { // No timeout in Java 6
throw new IOException("Timeout reached while waiting for UUID from WMIC!");
}
br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = br.readLine()) != null) {
if (null != line) {
line = line.replace("\t", "").replace(" ", "");
if (!line.isEmpty() && !line.equalsIgnoreCase("UUID")) {
uuid = line.replace("-", "");
}
}
}
} catch (IOException | InterruptedException ex) {
uuid = null;
SimpleLogger.error(
"Failed to retrieve machine UUID from WMIC!" + SimpleLogger.getPrependedStackTrace(ex)
);
// ex.printStackTrace(System.err);
} finally {
if (null != br) {
try {
br.close();
} catch (IOException ex) {
SimpleLogger.warn(
"Failed to close buffered reader while retrieving machine UUID!"
);
}
if (null != p) {
p.destroy();
}
}
}
return uuid;
}
You can use the following code which only uses features available under Java 6:
public static boolean waitFor(Process p, long t, TimeUnit u) {
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
final AtomicReference<Thread> me = new AtomicReference<Thread>(Thread.currentThread());
ScheduledFuture<?> f = ses.schedule(new Runnable() {
#Override public void run() {
Thread t = me.getAndSet(null);
if(t != null) {
t.interrupt();
me.set(t);
}
}
}, t, u);
try {
p.waitFor();
return true;
}
catch(InterruptedException ex) {
return false;
}
finally {
f.cancel(true);
ses.shutdown();
// ensure that the caller doesn't get a spurious interrupt in case of bad timing
while(!me.compareAndSet(Thread.currentThread(), null)) Thread.yield();
Thread.interrupted();
}
}
Note that unlike other solutions you can find somewhere, this will perform the Process.waitFor() call within the caller’s thread, which is what you would expect when looking at the application with a monitoring tool. It also helps the performance for short running sub-processes, as the caller thread will not do much more than the Process.waitFor(), i.e. does not need to wait for the completion of background threads. Instead, what will happen in the background thead, is the interruption of the initiating thread if the timeout elapsed.
I have test with small beanshell-script when i get from csv-file some names (like cars,telephones,blabla) and i have to check this names in html from previous test-step. Result of every check i have to write in other file. My issue here is mark this step to red color if at least one name wasn't find in html. Code here:
String Response = prev.getResponseDataAsString();
try {
File file = new File(vars.get("pathtocsv"));
FileReader fr = new FileReader(file);
BufferedReader reader = new BufferedReader(fr);
String line = reader.readLine();
if (line != null) {
String[] parts = line.split(",");
try{
FileWriter fw = new FileWriter(vars.get("pathtoresults"), true);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter pw = new PrintWriter(bw);
for(String i : parts) {
String utf8String= new String(i.getBytes("windows-1251"), "UTF-8");
if(Response.contains(utf8String)){
pw.println("Response contain element: " + i);
}
else{
pw.println("!!! Response doesn't contain element: " + i);
Failure=true;
FailureMessage = "!!! Response doesn't contain element: " + i;
log.warn( "!!! Response doesn't contain element " + utf8String);
prev.setResponseCode("400");
}
}
pw.close();
}
catch (IOException e){
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
prev is a shorthand to SampleResult class instance so you can conditionally mark sampler as failed from the PostProcessor using prev.setSuccessful(false) method.
Be aware that Beanshell is not the recommended scripting option, starting from JMeter version 3.1 users are strongly encouraged to switch to JSR223 Test Elements and Groovy language as Groovy is more Java compliant, has a lot of JDK enhancements and performs much better. See Apache Groovy - Why and How You Should Use It for more details.
You can fail parent sampler by marking success as false:
prev.setSuccessful(false);
I want to implement a distributed priority queue without using Zookeeper?
If you know how to communicate between client and server (e.g. with TCP sockets) it should be straightforward. The server contains a thread safe implementation of the Priority Queue, hence providing an "interface". Clients connect to the server and uses this "interface".
Server
The server must provide a priority queue interface (i.e. supporting add, peek, poll, ...). Important is that these methods must be thread safe ! So we will use PriorityBlockingQueue (which is synchronized) instead of PriorityQueue.
public class Server {
private static ServerSocket server_skt;
public PriorityBlockingQueue<Integer> pq;
// Constructor
Server(int port, int pq_size) {
server_skt = new ServerSocket(port);
this.pq = new PriorityBlockingQueue<Integer>(pq_size);
}
public static void main(String argv[]) {
Server server = new Server(5555, 20); // Make server instance
while(true) {
// Always wait for new clients to connect
try {
System.out.println("Waiting for a client to connect...");
// Spawn new thread for communication with client
new CommunicationThread(server_skt.accept(), server.pq).start();
} catch(IOException e) {
System.out.println("Exception occured :" + e.getStackTrace());
}
}
}
}
And this is how CommunicationThread class would look like
public class CommunicationThread extends Thread {
private Socket client_socket;
private InputStream client_in;
private OutputStream client_out;
private PriorityBlockingQueue<Integer> pq;
public CommunicationThread(Socket socket, PriorityBlockingQueue<Integer> pq) {
try {
this.client_socket = socket;
this.client_in = client_socket.getInputStream();
this.client_out = client_socket.getOutputStream();
this.pq = pq;
System.out.println("Client connected : " + client_socket.getInetAddress().toString());
} catch(IOException e) {
System.out.println("Could not initialize communication properly. -- CommunicationThread.\n");
}
}
#Override
public void run() {
boolean active = true;
while(active) {
int message_number = client_in.read(); // Listen for next integer --> dispatch to correct method
switch(message_number) {
case -1: case 0:
// Will stop the communication between client and server
active = false;
break;
case 1:
// Add
int element_to_add = client_in.read(); // read element to add to the priority queue
pq.add(element_to_add); // Note that a real implementation would send the answer back to the client
break;
case 2:
// Poll (no extra argument to read)
int res = pq.poll();
// Write result to client
client_out.write(res);
client_out.flush();
break;
/*
* IMPLEMENT REST OF INTERFACE (don't worry about synchronization, PriorityBlockingQueue methods are already thread safe)
*/
}
}
client_in.close();
client_out.close();
}
}
This class is listening to what the client is sending.
According to what the client sent, the server knows what to do, hence there is a mini protocol. That protocol is : when the client wants to invoke a method of the distributed priority queue, he sends an integer (e.g. 2 = poll()). The server reads that integer and knows which method to invoke.
Note that sometimes sending one integer is enough (see poll() example), but not always. Think for example of add() which has to specify an argument. The server will receive 1 from the client (i.e. add()) and will read a second integer (or any other object that has to be stored in the distributed priority queue).
Client
Based on the protocol, the server is offering the client an interface (e.g. 0 = stop communication, 1 = add() , ...). The client only has to connect to the server and send messages (respecting the procotol!) to it.
A client example :
public class PQ_Client {
private static Socket skt;
private InputStream in;
private OutputStream out;
private final int _STOP_ = 0, _ADD_ = 1, _POLL_ = 2; // By convention (protocol)
PQ_Client(String ip, int port) {
try {
this.skt = new Socket(ip, port);
this.in = skt.getInputStream();
this.out = skt.getOutputStream();
System.out.println("Connected to distributed priority queue.");
} catch(IOException e) {
System.out.println("Could not connect with the distributed priority queue : " + e.getStackTrace());
}
}
// Sort of stub functions
public void stop() {
out.write(_STOP_);
out.flush();
out.close();
}
public void add(Integer el) {
out.write(_ADD_); // Send wanted operation
out.write(el); // Send argument element
// Real implementation would listen for result here
out.flush();
}
public int poll() {
out.write(_POLL_);
out.flush();
// Listen for answer
return in.read();
}
/*
* Rest of implementation
*/
}
Note that thanks to these self made "stub functions" we can make a PQ_Client object and use it as if it was a priority queue (the client/server communication is hidden behind the stubs).
String ip = "...";
int port = 5555;
PQ_Client pq = new PQ_Client(ip , port);
pq.add(5);
pq.add(2);
pq.add(4);
int res = pq.poll();
Note that by using RPC (Remote Procedure Call) it could be easier (stub function generated automatically, ...).
In fact what we implemented above is a little RPC-like mechanism, as it does nothing else then sending a message to call a procedure (e.g. add()) on the server, serializing the result (not needed for integers), send it back to the client.
Im trying to send a Protocol buffer message from a Java Client to a C++ Server. After runing the server and the client i just get "0" as a value for the Api field, even i set it as "1" in the Java client side.
The Java Client code looks like this:
public static void main(String[] args) throws IOException {
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
//the protocol buffers message is called INFO and have only one field Api
INFO info = INFO.newBuilder()
.setApi(1)
.build();
try {
echoSocket = new Socket("localhost", 30000);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: Localhost.");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for "
+ "the connection to: Localhost.");
System.exit(1);
}
out.println((info.toByteArray())); // serialize and the message
System.out.println("send ");
}
}
And the C++ server code looks like this:
int main ( int argc, int argv[] ){
INFO info;
try
{
// Create the socket
ServerSocket server ( 30000 );
while ( true )
{
ServerSocket new_sock;
server.accept ( new_sock );
try
{
while(true){
std::string data;
// in the next i'll i receive Data from the Java client i already test it with a string, and it works
new_sock >> data;
info.ParseFromString(data);
cout << "api: " << info.api() << endl;
}
}
catch ( SocketException& ) {}
}
}
catch ( SocketException& e )
{
std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
}
return 0;
}
I am not sure what I am doing wrong. I don't know if I am serializing an parsing correctly. i didn't get any errors only a false Api value. Please let me know if you see any problems! Thanks a lot!
I think the problem is with:
new_sock >> data;
Verify that the number of bytes read in for data is the same as the size of info.toByteArray(). My guess is they're different, in which case you need to change the way that you're read(2)ing data from new_sock (newline delimited IO by default?).