I'm writing a little java program to write data in a AS/400 DB2 table via jdbc (db2jcc.jar version 1.0.581) and a trigger is associated to the INSERT operation. This trigger works on various tables associated with libraries different from that (jdta73p10) which contains my table (f4104).
Follows the code I use to establish connection and read data that perfectly runs.
import java.sql.*;
import com.ibm.db2.jcc.*;
public class ProvaNUMEAN13 {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
DB2DataSource dbds = new DB2DataSource();
dbds.setDriverType(4);
dbds.setServerName("a60d45bb");
dbds.setPortNumber(446);
dbds.setDatabaseName("prodgrp");
dbds.setDescription("Prova collegamento");
dbds.setUser("XXXXX");
dbds.setPassword("XXXXX");
Connection con = dbds.getConnection();
Statement stmtNum = con.createStatement();
stmtNum.executeQuery("select * from INTERFACCE.NUMEAN13");
ResultSet rs = stmtNum.getResultSet();
rs.next();
System.out.println("Valore numeratore: " + rs.getString("E13EAN"));
System.out.println("Tipo numeratore: " + rs.getString("K13KEY"));
stmtNum.close();
Statement stmtAnag = con.createStatement();
stmtAnag.executeQuery("select * from jdta73p10.f4101lb where IMLITM = " + "'" + args[0] + "'");
ResultSet rsAna = stmtAnag.getResultSet();
int idCodice = 0;
if (!rsAna.next()) {
System.out.println("Il codice " + args[0] + " non esiste in anagrafica!");
} else {
idCodice = rsAna.getInt("IMITM");
System.out.println("idCodice per " + args[0] + ": " + Integer.toString(idCodice));
Statement stmtQEAN = con.createStatement();
stmtQEAN.executeQuery("select IVALN, IVCITM, IVLITM, IVDSC1 from jdta73p10.f4104 where IVXRT = 'B ' and IVALN = '8000000000000'");
ResultSet rsQEAN = stmtQEAN.getResultSet();
if (rsQEAN.next()) {
System.out.println("Codice EAN per " + args[0] + " giĆ presente: " + rsQEAN.getString("IVALN"));
System.out.println("Valore EAN13: " + rsQEAN.getString("IVCITM"));
System.out.println("Risultato ricerca per EAN13: " + rsQEAN.getString("IVLITM")+" - "+rsQEAN.getString("IVDSC1"));
}
}
}
}
Problem is when I try to execute an INSERT operation (like that below); an error is generated in AS/400 due to trigger execution.
stmtQEAN.execute("insert into jdta73p10.f4104 (IVXRT,IVITM,IVCITM,IVDSC1,IVALN,IVLITM) values ('B ','18539','8000000000000','Prodotto PROVA','8000000000000','ABABABAB')");
This is the error AS/400 side:
Message ID . . . . . . : RNQ0211 Severity . . . . . . . : 99
Message type . . . . . : Inquiry
Date sent . . . . . . : 08/01/15 Time sent . . . . . . : 10:01:31
Message . . . . : Error occurred while calling program or procedure
*LIBL/PRHWRAPUSE (C G D F).
Cause . . . . . : RPG procedure TRG_F4104A in program INTERFACCE/TRG_F4104A at
statement 152 attempted to call program or procedure *LIBL/WS_MATERI, but
was unable to access the program or procedure, the library, or a required
service program. If the name is *N, the call was a bound call by procedure
pointer.
Recovery . . . : Check the job log for more information on the cause of the
error and contact the person responsible for program maintenance.
Possible choices for replying to message . . . . . . . . . . . . . . . :
D -- Obtain RPG formatted dump.
S -- Obtain system dump.
My question is: how can I specify the other libraries that trigger need? In a old version of my tools (written in Delphi) I used the Client/Access ODBC where there was a special field where you can enter additional libraries but now I don't know how to do.
AS400 (iSeries) allows a comma-separated library list in the jdbc url:
jdbc:as400://someserver;naming=system;libraries=devfiles,prodfiles,sysibm,etc
naming=system indicates sql will use a library list. For example:
select * from NUMEAN13
naming=sql indicates that sql will contain library name prefixed in table references. For example:
select * from INTERFACCE.NUMEAN13
My experience is that you can't mix them. If you use library list (naming=system), then all sql must not contain library names. If you use non library list (naming=sql), then all sql must contain the library names.
There are several ways to handle this. The user profile has a job description and that job description has a library list. I would set up a user profile / job description combination for your JDBC connexion.
If that isn't dynamic enough, consider writing a stored procedure that you can call which will set the library list the way you need it.
Another way is probably too inflexible but I mention it as an alternative. Instead of using *LIBL for the service program, specify the library. On the one hand this makes it impossible to use the same program in test and production. On the other hand, it makes it impossible for someone to insert their own library in the middle.
If you are really stuck and no one on the IBM side is able to make changes for you, you can CALL QCMDEXC as a stored procedure and alter the library list yourself, from the client. This is the least desirable because it means tight coupling between the client and server. If the IBM team ever trues to set up a test environment (or disaster recovery environment!) you will have to change all the references in your client code and distribute the changes to everyone using it.
Thank you for the tips.
I also was thinking to use a stored procedure (as you suggest) but in the end I discovered that using an other IBM package, jt400.jar, is available a DataSource class with a method to set a list of AS/400 libraries that you need to use.
Below how I modified my code (that now works!) using the method setLibraries.
import com.ibm.as400.access.*;
...
AS400JDBCDataSource dbds = new AS400JDBCDataSource();
dbds.setServerName("a60d45bb");
// dbds.setPortNumber(446);
dbds.setDatabaseName("prodgrp");
dbds.setDescription("Prova collegamento a numeratore EAN13");
dbds.setUser("XXXXX");
dbds.setPassword("XXXXX");
dbds.setLibraries("JCOM73P10 JDTA73P10 KLDADBFER KLDADBGAM INTERFACCE SAP");
Connection con = dbds.getConnection();
This class has not available the method setPort but if you use the standard port (like in my case) there are no problems. If will be necessary I'll try to discover how to set it.
Couple solutions.
quick real time fix
Copy the trigger program to QGPL (Temporary fix. A permanent fix would need to be implemented ASAP)
or
Change the JOBD of the user profile used to connect to the AS400 so it has the correct list. The user profile used for JDBC should already be locked down or it's the jdbc of a user in a group so this is a simple CHGJOBD JOBD(x) LIBL(xxx xxx xxx xxx) but the connections will have to be recycled.
or
Change the trigger program so that it has a hard coded library. I'd bet you'd need exclusive access to the file though. I'm not working (no access to iseries) so I can't verify this solution.
I recommend against changing the connection string. You'll end up having to change it for every machine that connects to the database.
Related
Our production instance of NiFi is version 1.8.0. We have a custom processor that continually looks at it's downstream connections in order to route flow files based on the connection's queue size.
Here is the salient snippet of how we do this . . .
String processorId = this.getIdentifier();
ProcessorGroupStatus processGroupStatus = ((EventAccess) getControllerService()).getContollerStatus();
Collection<ConnectionStatus> groupConnections = processGroupStatus.getConnectionStatus();
ArrayList connections = new ArrayList<>(groupConnections);
for (Object processorConnection : connections) {
ConnectionStatus connection = (ConnectionStatus) processorConnection;
if(connection.getSourceId().equals(processorId){
//do stuff with connection.getQueuedCount() & connection.getQueuedBytes()
break;
}
}
Everything has been working as expected for the last couple of years. However, upgrading our NiFi instance to version 1.11.4 has broken this approach. The exception thrown is:
class org.apache.nifi.contoller.serviceStandardContollerServiceProvider cannot be cast to class org.apache.nifi.reporting.EventAccess
Is there another way to retrieve connections from processContext?
One approach that may be more upwardly compatible (and easier to maintain) than a custom Java processor would be to use the ExecuteGroovyScript processor.
The Groovy script in this case would look something like:
ff = session.get()
if (ff) {
me = context.procNode
processorId = me.identifier
connections = me.processGroup.connections
connections.each { connection ->
if(connection.source.identifier.equals(processorId)) {
ff[connection.identifier] = "I am the source " +
"[" + connection.flowFileQueue.size().objectCount + "]" +
"[" + connection.flowFileQueue.size().byteCount + "]"
}
else {
ff[connection.identifier] = "I am NOT the source; my name is [" + connection.name + "]"
}
}
REL_SUCCESS << ff
}
To find out what is available to the Groovy script, I use a combination of the NiFi JavaDocs (https://javadoc.io/static/org.apache.nifi/nifi-api/1.12.0/index.html) and the Github code for NiFi (https://github.com/apache/nifi/tree/c396927299586b896df4ebc745793b4c451f3898/nifi-api/src/main/java/org/apache/nifi).
As a side note, we converted our custom Java processors to Groovy script, because of an upgrade incompatibility when going to (ironically) 1.8.0. We have not had an issue with NiFi upgrades since then, and are currently running v 1.11.4.
I try to test the jdbc connection of snowflake with codes below
Connection conn = .......
.......
ResultSet rs = conn.getMetaData().getColumns(**null**, "PUBLIC", "TAB1", null); // 1. set parameters to get metadata of table TAB1
while (rs.next()) { // 2. It hangs here if the first parameter is null in above liune; otherwise(set the corrent db name), it works fine
System.out.println( "precision:" + rs.getInt(7)
+ ",col type name:" + rs.getString(6)
+ ",col type:" + rs.getInt(5)
+ ",col name:" + rs.getString(4)
+ ",CHAR_OCTET_LENGTH:" + rs.getInt(16)
+ ",buf LENGTH:" + rs.getString(8)
+ ",SCALE:" + rs.getInt(9));
}
.......
I debug the codes above in Intellij IDEA, and find that the debugger can't get the details of the object, it always shows "Evaluating..."
The JDBC driver I used is snowflake-jdbc-3.12.5.jar
Is it a bug?
When the catalog (database) argument is null, the JDBC code effectively runs the following SQL, which you can verify in your Snowflake account's Query History UIs/Views:
show columns in account;
This is an expensive metadata query to run due to no filters and the wide requested breadth (columns across the entire account).
Depending on how many databases exist in your organization's account, it may require several minutes or upto an hour of execution to return back results, which explains the seeming "hang". On a simple test with about 50k+ tables dispersed across 100+ of databases and schemas, this took at least 15 minutes to return back results.
I debug the codes above in Intellij IDEA, and find that the debugger can't get the details of the object, it always shows "Evaluating..."
This may be a weirdness with your IDE, but in a pinch you can use the Dump Threads (Ctrl + Escape, or Ctrl + Break) option in IDEA to provide a single captured thread dump view. This should help show that the JDBC client thread isn't hanging (as in, its not locked or starved), it is only waiting on the server to send back results.
There is no issue with the 3.12.5 jar.I just tested the same version in Eclipse, I can inspect all the objects . Could be an issue with your IDE.
ResultSet columns = metaData.getColumns(null, null, "TESTTABLE123",null);
while (columns.next()){
System.out.print("Column name and size: "+columns.getString("COLUMN_NAME"));
System.out.print("("+columns.getInt("COLUMN_SIZE")+")");
System.out.println(" ");
System.out.println("COLUMN_DEF : "+columns.getString("COLUMN_DEF"));
System.out.println("Ordinal position: "+columns.getInt("ORDINAL_POSITION"));
System.out.println("Catalog: "+columns.getString("TABLE_CAT"));
System.out.println("Data type (integer value): "+columns.getInt("DATA_TYPE"));
System.out.println("Data type name: "+columns.getString("TYPE_NAME"));
System.out.println(" ");
}
TL;DR: What Database.FileFormat constant should I use for an MS Access 2000-2003 database, when creating the Database object?
I have built a SAMBA test application using jCIFS. It allows me to create/overwrite files if given the correct authentication credentials, regardless of on which PC in the domain I use it.
I also have an application that uses uCanAccess/jackcess to connect to an MDB on a network share. However (from what I understand), it uses the credentials of the logged-in user, a number of whom have read-only access. Only system/network administrators have write permission.
The database in question is not password-protected. (I don't need to enter a password when opening it.)
My intention is to have the app ask for the administrator's Samba credentials before it writes to the DB, using those in the uCanAccess connection, so that it doesn't throw a java.nio.channels.NonWritableChannelException, as per the below stack trace:
java.nio.channels.NonWritableChannelException
at sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:747)
at com.healthmarketscience.jackcess.impl.PageChannel.writePage(PageChannel.java:310)
at com.healthmarketscience.jackcess.impl.PageChannel.writePage(PageChannel.java:247)
at com.healthmarketscience.jackcess.impl.TableImpl.writeDataPage(TableImpl.java:1980)
at com.healthmarketscience.jackcess.impl.TableImpl.addRows(TableImpl.java:2229)
at com.healthmarketscience.jackcess.impl.TableImpl.addRow(TableImpl.java:2067)
at net.ucanaccess.converters.UcanaccessTable.addRow(UcanaccessTable.java:44)
at net.ucanaccess.commands.InsertCommand.insertRow(InsertCommand.java:101)
at net.ucanaccess.commands.InsertCommand.persist(InsertCommand.java:148)
at net.ucanaccess.jdbc.UcanaccessConnection.flushIO(UcanaccessConnection.java:315)
at net.ucanaccess.jdbc.UcanaccessConnection.commit(UcanaccessConnection.java:205)
at net.ucanaccess.jdbc.AbstractExecute.executeBase(AbstractExecute.java:217)
at net.ucanaccess.jdbc.Execute.execute(Execute.java:46)
at net.ucanaccess.jdbc.UcanaccessPreparedStatement.execute(UcanaccessPreparedStatement.java:228)
at myapp.db.Digger.addTransaction(Digger.java:993)
at myapp.tasks.TransactionRunnable.run(TransactionRunnable.java:42)
at java.lang.Thread.run(Thread.java:745)
Update: I have tried using the smbFileChannel class by Gord Thompson and J. T. Alhborn, shown here. My code, based off the main class shown in that answer, looks like this:
// Ask the user for login credentials and the path to the database
String smbURL = (chosenDir.endsWith("/") ? chosenDir : chosenDir + '/')
+ dbName;
System.out.println("DB Path to use for URL: " + smbURL);
URL u = new URL(smbURL);
try (
// construct the SMB DB URL
SmbFileChannel sfc = new SmbFileChannel(smbURL);
Database db = new DatabaseBuilder().setChannel(sfc)
.setFileFormat(Database.FileFormat.GENERIC_JET4).create();
) {
// Model the table
Table tbl = new TableBuilder("Transactions")
.addColumn(new ColumnBuilder("TransactionID", DataType.LONG).setAutoNumber(true))
.addColumn(new ColumnBuilder("ControllerID", DataType.LONG).setAutoNumber(false))
.addColumn(new ColumnBuilder("ReaderID", DataType.LONG).setAutoNumber(false))
.addColumn(new ColumnBuilder("Event", DataType.LONG).setAutoNumber(false))
.addColumn(new ColumnBuilder("Timestamp", DataType.SHORT_DATE_TIME).setAutoNumber(false))
.addColumn(new ColumnBuilder("Number", DataType.LONG).setAutoNumber(false))
.addIndex(new IndexBuilder(IndexBuilder.PRIMARY_KEY_NAME).addColumns("TransactionID").setPrimaryKey())
.toTable(db);
// Add the row
Map<String, Object> values = new HashMap<>();
values.put("ControllerID", cid);
values.put("ReaderID", rid);
values.put("Event", evtNum);
values.put("Timestamp", ts); // Long; must be converted to DataType.SHORT_DATE_TIME
values.put("Number", accNum);
tbl.addRowFromMap(values);
} catch (IOException IOEx) {
System.err.println(
"Failed to write record to Transactions table in database: "
+ IOEx.getMessage()
);
IOEx.printStackTrace(System.err);
} catch (Exception ex) {
System.err.println(
'[' + ex.getClass().getSimpleName() + "]: Failed to write record to "
+ "Transactions table in database: " + ex.getMessage()
);
ex.printStackTrace(System.err);
}
Executing the above code results in the following output:
DB Path to use for URL: smb://machine.vpnName/Storage/me/dbs/DBName.mdb
Failed to write record to Transactions table in database: Logon failure: account currently disabled.
jcifs.smb.SmbAuthException: Logon failure: account currently disabled.
at jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:546)
at jcifs.smb.SmbTransport.send(SmbTransport.java:663)
at jcifs.smb.SmbSession.sessionSetup(SmbSession.java:390)
at jcifs.smb.SmbSession.send(SmbSession.java:218)
at jcifs.smb.SmbTree.treeConnect(SmbTree.java:176)
at jcifs.smb.SmbFile.doConnect(SmbFile.java:911)
at jcifs.smb.SmbFile.connect(SmbFile.java:957)
at jcifs.smb.SmbFile.connect0(SmbFile.java:880)
at jcifs.smb.SmbFile.open0(SmbFile.java:975)
at jcifs.smb.SmbFile.open(SmbFile.java:1009)
at jcifs.smb.SmbRandomAccessFile.<init>(SmbRandomAccessFile.java:57)
at jcifs.smb.SmbRandomAccessFile.<init>(SmbRandomAccessFile.java:42)
at samba.SmbFileChannel.<init>(SmbFileChannel.java:30)
at samba.SambaLanWriteTest.writeTest(SambaLanWriteTest.java:130)
at samba.SambaLanWriteTest.main(SambaLanWriteTest.java:181)
I have write access to a test copy of the database file in question when using Windows File Explorer. I am choosing that one when prompted.
Update 2: I realised that I neglected to add my username and password to the smb:// URL, as Thompson's example shows. I changed to code to this:
String smbCred = "smb://" + auth.getUsername() + ":" + auth.getPassword() + "#",
fixer = chosenDir.replace("\\", "/").replace("smb://", smbCred),
smbURL = fixer + dbName;
System.out.println("DB Path to use for URL: " + smbURL);
// URL u = new URL(smbURL);
The next problem I had was that my password contains special illegal characters (such as '#', ':', ';', '=' and '?'). I escaped these by using java.net.URLEncoder.encode() on auth.getUsername() and auth.getPassword() so the code doesn't throw a MalformedURLException when creating the SmbChannel. However, the next exception I encountered is as follows:
Failed to write record to Transactions table in database: File format GENERIC_JET4 [VERSION_4] does not support file creation for null
java.io.IOException: File format GENERIC_JET4 [VERSION_4] does not support file creation for null
at com.healthmarketscience.jackcess.impl.DatabaseImpl.create(DatabaseImpl.java:444)
What Database.FileFormat constant should I use for an MS Access 2000-2003 database, when creating the Database object?
It turns out that I needed to use Database.FileFormat.V2000.
After that, it was all plain sailing (although I still need to work out how to get the Long timestamp to convert correctly).
I am using SQL 'select' to access a db2 table with schemaname.tablename as follows:
select 'colname' from schemaname.tablename
The tablename has 'colname' = SERVER_POOL_NAME for sure . yet I get the following error :
"Invalid parameter: Unknown column name SERVER_POOL_NAME . ERRORCODE=-4460, SQLSTATE=null"
I am using db2 v10.1 FP0 jdbc driver version 3.63.123. JDBC 3.0 spec
The application is run as db2 administrator and also Windows 2008 admin
I saw a discussion about this issue at : db2jcc4.jar Invalid parameter: Unknown column name
But i do not know where the connection parameter 'useJDBC4ColumnNameAndLabelSemantics should be set ( to value =2)
I saw the parameter should appear in com.ibm.db2.jcc.DB2BaseDataSource ( see: http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/index.jsp?topic=%2Fcom.ibm.db2.luw.apdv.java.doc%2Fsrc%2Ftpc%2Fimjcc_r0052607.html)
But i do not find this file on my DB2 installation . maybe it is packed in a .jar file
Any advice ?
There is a link on the page you're referring to, showing you the ways to set properties. Specifically, you can populate a Properties object with desired values and supply it to the getConnection() call:
String url = "jdbc:db2://host:50000/yourdb";
Properties props = new Properties();
props.setProperty("useJDBC4ColumnNameAndLabelSemantics", "2");
// set other required properties
Connection c = DriverManager.getConnection(url, props);
Alternatively, you can embed property name/value pairs in the JDBC URL itself:
String url = "jdbc:db2://host:50000/yourdb:useJDBC4ColumnNameAndLabelSemantics=2;";
// set other required properties
Connection c = DriverManager.getConnection(url);
Note that each name/value pair must be terminated by a semicolon, even the last one.
I have created a JMeter functional test that essentially:
creates a user;
logs in with the user;
deletes the user.
Now, I need to be able to thread this, and dynamically generate a username with a default prefix and a numerically incremented suffix (ie TestUser_1, TestUser_2, ... etc).
I used the counter, and things were working fine until I really punched up the number of threads/loops. When I did this, I was getting a conflict with the counter. Some threads were trying to read the counter, but the counter had already been incremented by another thread. This resulted in trying to delete a thread that was just created, then trying to log in with a thread that was just deleted.
The project is set up like this:
Test Plan
Thread group
Counter
User Defined Variables
Samplers
I was hoping to solve this problem by using the counter to append a number to the user defined variables upon thread execution, but the counter cannot be accessed in the user defined variables.
Any ideas on how I can solve this problem?
Thank you in advance.
I've used the following scheme successfully with any amount of test users:
1. Generate using beanshell-script (in BeanShell Sampler e.g.) csv-file with test-user details, for example:
testUserName001,testPwd001
testUserName002,testPwd002
. . .
testUserName00N,testPwd00N
with the amount of entries you need for the test-run.
This is done once per "N users test-run", in separate Thread Group, in setUp Thread Group or maybe even in separate jmx-script... makes no difference.
You can please find working beanshell-code below.
2. Create your test users IN TEST APPLICATION using previously created users-list.
If you don't need create in application you may skip this.
Thread Group
Number of Threads = 1
Loop Count = 1
. . .
While Controller
Condition = ${__javaScript("${newUserName}"!="",)} // this will repeat until EOF
CSV Data Set Config
Filename = ${__property(user.dir)}${__BeanShell(File.separator,)}${__P(users-list,)} // path to generated users-list
Variable Names = newUserName,newUserPwd // these are test-users details read from file into pointed variables
Delimiter = '
Recycle on EOF? = False
Stop thread on EOF? = True
Sharing Mode = Current thread group
[CREATE TEST USERS LOGIC HERE] // here are actions to create separate user in application
. . .
3. Perform multi-user logic.
Schema like the given above one but Thread Group executed not for 1 but for N threads.
Thread Group
Number of Threads = ${__P(usersCount,)} // set number of users you need to test
Ramp-Up Period = ${__P(rampUpPeriod,)}
Loop Count = X
. . .
While Controller
Condition = ${__javaScript("${newUserName}"!="",)} // this will repeat until EOF
CSV Data Set Config
Filename = ${__property(user.dir)}${__BeanShell(File.separator,)}${__P(users-list,)} // path to generated users-list
Variable Names = newUserName,newUserPwd // these are test-users details read from file into pointed variables
Delimiter = '
Recycle on EOF? = False
Stop thread on EOF? = True
Sharing Mode = Current thread group
[TEST LOGIC HERE] // here are test actions
. . .
The key idea is in using Thread Group + While Controller + CSV Data Set Config combination:
3.1. CSV Data Set Config reads details for each the test users from generated file:
. . . a. only once - because of "Stop thread on EOF? = True";
. . . b. doesn't block file for further access (in another thread groups, e.g., if there are any) - because of "Sharing Mode = Current thread group";
. . . c. pointed variables - "Variable Names = newUserName,newUserPwd" - you will use in further test-actions;
3.2. While Controller forces CSV Data Set Config to read all the entries from generated file - because of defined condition (until the EOF).
3.3. Thread Group will start all the threads with defined ramp-up - or simultaneously if ramp-up = 0.
You can take here template script for described schema: multiuser.jmx.
Beanshell script to generate test-users details looks like below and takes the following args:
- test-users count
- test-user name template ("TestUser_" in your case)
- test-user name format (e.g. 0 - to get TestUser_1, 00 - to get TestUser_01, 000- for TestUser_001, etc... you can simply hardcode this orexclude at all)
- name of generated file.
import java.text.*;
import java.io.*;
import java.util.*;
String [] params = Parameters.split(",");
int count = Integer.valueOf(params[0]);
String testName = params[1];
String nameFormat = params[2];
String usersList = params[3];
StringBuilder contents = new StringBuilder();
try {
DecimalFormat formatter = new DecimalFormat(nameFormat);
FileOutputStream fos = new FileOutputStream(System.getProperty("user.dir") + File.separator + usersList);
for (int i = 1; i <= count; i++) {
String s = formatter.format(i);
String testUser = testName + s;
contents.append(testUser).append(",").append(testUser);
if (i < count) {
contents.append("\n");
}
}
byte [] buffer = contents.toString().getBytes();
fos.write(buffer);
fos.close();
}
catch (Exception ex) {
IsSuccess = false;
log.error(ex.getMessage());
System.err.println(ex.getMessage());
}
catch (Throwable thex) {
System.err.println(thex.getMessage());
}
All together it will look like:
Sorry if answer is too overloaded.
Hope this helps.
The "User Defined Variables" config element does not pick up the reference variable from the "Counter" config element. I think this is a bug in JMeter. I have verified this behavior in version 3.2.
I added a "BeanShell Sampler" element to work around the issue.
Notice that the reference name of the "Counter" element is INDEX
The RUN_FOLDER variable gets set to a combination of the TESTS_FOLDER variable and the INDEX variable in the "BeanShell Sampler"
The "Debug Sampler" simply gathers a snapshot of the variables so I can see them in the "View Results Tree" listener element. Notice how the RUN_FOLDER variable has the INDEX variable value (5 in this case) appended.