How to run a JMeter JMX file in Java code? - java

I am trying to run a JMeter MS SQL database test plan from Java code through my Spring Boot app but it's showing the following errors:
I have loaded the plugin manager in JMeter and put that in jmeter/lib/ext folder and installed all required plugins.
Java code to run JMeter test case:
package com.example.demofin;
import java.io.File;
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.reporters.ResultCollector;
import org.apache.jmeter.reporters.Summariser;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import com.example.demofin.config.Properties;
#Component
public class Demofin implements CommandLineRunner {
#Autowired
private Properties properties;
private Summariser result;
#Override
public void run(String... args) throws Exception {
for(String i : args)
System.out.println(i);
// String j = properties.getPropertyByKey("JMETER_HOME");
String j="D:\\apache-jmeter-4.0";
// System.out.println(j);
//System.out.println("Jmeter home path: " + properties.getPropertyByKey("JMETER_HOME"));
StandardJMeterEngine jmeter = new StandardJMeterEngine();
// // Initialize Properties, logging, locale, etc.
JMeterUtils.setJMeterHome(j);
JMeterUtils.loadJMeterProperties(j+"/bin/jmeter.properties");
//
// // you can comment this line out to see extra log messages of i.e. DEBUG level
JMeterUtils.initLogging();
JMeterUtils.initLocale();
// Initialize JMeter SaveService
SaveService.loadProperties();
// Load existing .jmx Test Plan
HashTree testPlanTree = SaveService.loadTree(new File("D:\\apache-jmeter-4.0\\" + "bin\\JDBC Connection Configuration.jmx"));
Summariser summer = null;
String summariserName = JMeterUtils.getPropDefault("summariser.name", "summary");
if (summariserName.length() > 0) {
summer = new Summariser(summariserName);
}
ResultCollector logger = new ResultCollector(summer);
testPlanTree.add(testPlanTree.getArray()[0], logger);
// Run JMeter Test
jmeter.configure(testPlanTree);
jmeter.run();
result = summer;
}
}

Usually, we compile java code to jar and push it to jmeter/lib/ext and use it in Jmeter.
If you attempt to using Jmeter in java, I suggest downloading source code of JMeter and merge to your project.

Related

Load neo4j dump in test container during integration test run

I am trying to write integration test for neo4j using spring boot. I am using test container. Can anyone help me how to load database dump file to testcontainer?
here's one way to do this (using current Neo4j 5.3). I have a dump file called neo4j.dump created from a local instance and I use withCopyFileToContainer to copy it to the container before it starts.
As I use the community edition in this example, there is no online backup/restore, but only dump/load. So therefor I have to change the startup command. The load needs to happen before Neo4j starts. I can't stop Neo4j in the container because it would stop the container.
Therefor I create a small shell script that executes the desired other command and than delegates to the original entry point.
This script is transferred with file mode 0100555, corresponding to r-xr-xr-x so that it is executable.
Finally, the container is started with the above script as command.
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.images.builder.Transferable;
import org.testcontainers.utility.MountableFile;
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class LoadDumpTest {
Neo4jContainer<?> neo4j;
Driver driver;
#BeforeAll
void initNeo4j() {
neo4j = new Neo4jContainer<>("neo4j:5.3.0")
.withCopyFileToContainer(MountableFile.forClasspathResource("neo4j.dump"),
"/var/lib/neo4j/data/dumps/neo4j.dump")
.withCopyToContainer(Transferable.of("""
#!/bin/bash -eu
/var/lib/neo4j/bin/neo4j-admin database load neo4j
/startup/docker-entrypoint.sh neo4j
""", 0100555), "/startup/load-dump-and-start.sh")
.withCommand("/startup/load-dump-and-start.sh")
.withLogConsumer(f -> System.out.print(f.getUtf8String()));
neo4j.start();
driver = GraphDatabase.driver(neo4j.getBoltUrl(), AuthTokens.basic("neo4j", neo4j.getAdminPassword()));
}
#Test
void dataShouldHaveBeenLoaded() {
try (var session = driver.session()) {
var numNodes = session.run("MATCH (n) RETURN count(n)").single().get(0).asLong();
Assertions.assertTrue(numNodes > 0);
}
}
#AfterAll
void stopNeo4j() {
neo4j.stop();
}
}
Edit:
If you are on a recent enterprise edition, Christophe suggested the following solution on Twitter, which I do personally think it's superior, as it is less hacky.
https://github.com/ikwattro/neo4j-5-testcontainers-restore-backup/blob/main/src/test/java/dev/ikwattro/Neo4j5RestoreBackupExampleTest.java
It makes use of seed URIs for databases. Copying or binding the resource in his example works the same as in mine.
If you're using Neo4j 5, I suggest you make backups instead of dumps. Using backups you can take advantage of the seedUri option when creating a database, meaning you can create a database from an URI pointing to a backup on disk ( or in the neo4j container ). https://neo4j.com/docs/operations-manual/current/clustering/databases/#cluster-seed-uri
Here is an example using Testcontainers
package dev.ikwattro;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.Session;
import org.neo4j.driver.SessionConfig;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import static org.assertj.core.api.Assertions.assertThat;
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#Testcontainers(disabledWithoutDocker = true)
public class Neo4j5RestoreBackupExampleTest {
#Container
private Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5.3.0-enterprise")
.withAdminPassword("password")
.withEnv("NEO4J_dbms_memory_heap_max__size", "256M")
.withEnv("NEO4J_dbms_databases_seed__from__uri__providers", "URLConnectionSeedProvider")
.withClasspathResourceMapping("backups", "/backups", BindMode.READ_ONLY)
.withEnv("NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes");
#BeforeAll
void beforeAll() {
neo4j.start();
createDbFromBackup();
}
#Test
void testCreatingDbFromBackup() {
try (Driver driver = GraphDatabase.driver(neo4j.getBoltUrl(), AuthTokens.basic("neo4j", "password"))) {
try (Session session = driver.session(SessionConfig.forDatabase("worldcup22"))) {
var result = session.run("MATCH (n) RETURN count(n) AS c").single().get("c").asLong();
assertThat(result).isPositive();
}
}
}
private void createDbFromBackup() {
try (Driver driver = GraphDatabase.driver(neo4j.getBoltUrl(), AuthTokens.basic("neo4j", "password"))) {
try (Session session = driver.session(SessionConfig.forDatabase("system"))) {
session.run("""
CREATE DATABASE worldcup22 OPTIONS { existingData: "use", seedUri: "file:///backups/world-cup-2022-neo4j.backup"}
""");
}
}
}
}
You can find a working maven project here https://github.com/ikwattro/neo4j-5-testcontainers-restore-backup

Caused by: java.lang.NoClassDefFoundError: software/constructs/Construct

I’m beginner to Terraform CDK. I’ve created simple code in terraform CDK to create an EC2 instance. but here instead of run cdktf deploy in terminal I’m calling is via java processbuilder inside my main method.
Every thing good till now. My Code is compile successful and Jar build. But we I run the jar by command java -jar target/ getting the below error.
└─[$] java -jar target/irm-1.0-SNAPSHOT.jar [0:24:43]
Error: Unable to initialize main class com.example.test.Main
Caused by: java.lang.NoClassDefFoundError: software/constructs/Construct
Here is the my file structure
Here is the Main.java
package com.example.test;
import com.hashicorp.cdktf.App;
import com.hashicorp.cdktf.TerraformStack;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
final App app = new App();
TerraformStack stack = new MainStack(app, "aws_instance");
// new RemoteBackend(stack, RemoteBackendProps.builder()
// .hostname("app.terraform.io")
// .organization("<YOUR_ORG>")
// .workspaces(new NamedRemoteWorkspace("learn-cdktf"))
// .build());
app.synth();
//calling cdktf deploy
List<String> list = new ArrayList<String>();
list.add("/usr/local/bin/cdktf");
list.add("deploy");
// create the process
ProcessBuilder build = new ProcessBuilder(list);
// starting the process
Process process = build.start();
// for reading the output from stream
BufferedReader stdInput
= new BufferedReader(new InputStreamReader(
process.getInputStream()));
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
}
}
Here is the MainStack.java
package com.example.test;
import software.constructs.Construct;
import com.hashicorp.cdktf.TerraformStack;
import com.hashicorp.cdktf.TerraformOutput;
import com.hashicorp.cdktf.providers.aws.AwsProvider;
import com.hashicorp.cdktf.providers.aws.ec2.Instance;
public class MainStack extends TerraformStack
{
public MainStack(final Construct scope, final String id) {
super(scope, id);
AwsProvider.Builder.create(this, "AWS")
.region("ap-south-1")
.build();
Instance instance = Instance.Builder.create(this, "compute")
.ami("ami-0e18b1d379af4e263")
.instanceType("t3a.micro")
.build();
TerraformOutput.Builder.create(this, "public_ip")
.value(instance.getPublicIp())
.build();
}
}
There are two problems I can spot here:
The error you are getting hints towards the construct package not being installed in this project. I'd recommend using the "normal" workflow of running your cdktf program by running cdktf synth or cdktf deploy in the CLI. You can also compile your program (it it's a standard program like we initialize it) by running mvn -e -q compile
It seems like you are trying to execute deploy from within your cdktf program. This won't work, it will create an infinite loop since this program is being run by the synth operation that is being run before the deploy executes. If you want to start cdktf programmatically it has to be from another program that is independent from you CDKTF application

How to use Throughput Shaping Timer from JMETER API using Java code?

enter image description here
1: https://i.stack.imgur.com/sRx3n.jpg**strong text**##
I am trying to write the Java program to get the input something like this for multiple rows and process it by creating concurrency thread group which can generate number of threads from tstfeedback function and complete the execution.enter image description here
Here is an example of creating an empty Test Plan with the Throughput Shaping Timer configured like at your first image via JMeter API:
import kg.apc.jmeter.JMeterPluginsUtils;
import kg.apc.jmeter.timers.VariableThroughputTimer;
import kg.apc.jmeter.timers.VariableThroughputTimerGui;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.gui.ArgumentsPanel;
import org.apache.jmeter.control.gui.TestPlanGui;
import org.apache.jmeter.gui.util.PowerTableModel;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestPlan;
import org.apache.jmeter.testelement.property.CollectionProperty;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ThroughputShapingTImer {
public static void main(String[] args) throws IOException {
File jmeterHome = new File("c:/apps/jmeter");
String slash = System.getProperty("file.separator");
File jmeterProperties = new File(jmeterHome.getPath() + slash + "bin" + slash + "jmeter.properties");
//JMeter initialization (properties, log levels, locale, etc)
JMeterUtils.setJMeterHome(jmeterHome.getPath());
JMeterUtils.loadJMeterProperties(jmeterProperties.getPath());
JMeterUtils.initLocale();
// JMeter Test Plan, basically JOrphan HashTree
HashTree testPlanTree = new HashTree();
//Throughput Shaping Timer
VariableThroughputTimer throughputShapingTimer = new VariableThroughputTimer();
throughputShapingTimer.setName("Timer");
PowerTableModel load_profile = new PowerTableModel(new String[]{"Start RPS", "End RPS", "Duration, sec"}, new Class[]{String.class, String.class, String.class});
load_profile.addRow(new Integer[]{0, 10, 20});
load_profile.addRow(new Integer[]{10, 10, 20});
CollectionProperty data = JMeterPluginsUtils.tableModelRowsToCollectionProperty(load_profile, VariableThroughputTimer.DATA_PROPERTY);
throughputShapingTimer.setData(data);
throughputShapingTimer.setProperty(TestElement.TEST_CLASS, VariableThroughputTimer.class.getName());
throughputShapingTimer.setProperty(TestElement.GUI_CLASS, VariableThroughputTimerGui.class.getName());
// Test Plan
TestPlan testPlan = new TestPlan("Create JMeter Script From Java Code");
testPlan.setProperty(TestElement.TEST_CLASS, TestPlan.class.getName());
testPlan.setProperty(TestElement.GUI_CLASS, TestPlanGui.class.getName());
testPlan.setUserDefinedVariables((Arguments) new ArgumentsPanel().createTestElement());
// Construct Test Plan from previously initialized elements
testPlanTree.add(testPlan);
HashTree threadGroupHashTree = testPlanTree.add(testPlan);
threadGroupHashTree.add(throughputShapingTimer);
// save generated test plan to JMeter's .jmx file format
SaveService.saveTree(testPlanTree, Files.newOutputStream(Paths.get("example.jmx")));
}
}
The resulting .jmx test plan will be stored in the current folder.
More information: Five Ways To Launch a JMeter Test without Using the JMeter GUI

How to add the request body data in the post request for JMeter testing using Java code in the non-GUI mode?

This is a Jmeter POST request in the form of a java code. I run this code to get no errors but I also get no response because my method of acting the request body data appears to be wrong.
import java.io.FileOutputStream;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.gui.ArgumentsPanel;
import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.control.gui.LoopControlPanel;
import org.apache.jmeter.control.gui.TestPlanGui;
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.protocol.http.control.Header;
import org.apache.jmeter.protocol.http.control.HeaderManager;
import org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui;
import org.apache.jmeter.protocol.http.gui.HeaderPanel;
//import org.apache.jmeter.protocol.http.sampler.HTTPSampler;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.apache.jmeter.reporters.ResultCollector;
import org.apache.jmeter.reporters.Summariser;
//import org.apache.jmeter.samplers.SampleEvent;
//import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.SampleSaveConfiguration;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestPlan;
import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jmeter.threads.gui.ThreadGroupGui;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;
import org.apache.jmeter.protocol.http.util.HTTPArgument;
public class PostRequest {
public static void main(String[] argv) throws Exception {
//JMeter Engine
StandardJMeterEngine jmeter = new StandardJMeterEngine();
//JMeter initialization (properties, log levels, locale, etc)
JMeterUtils.setJMeterHome("/C:/Users/xxx");
JMeterUtils.loadJMeterProperties("/C:/xxx");
JMeterUtils.initLogging();
JMeterUtils.initLocale();
//JMeter Test Plan, basically JOrphan HashTree
HashTree testPlanTree = new HashTree();
//HTTP Sampler
HTTPSamplerProxy httpSampler = new HTTPSamplerProxy();
httpSampler.setDomain("100.100.100.100");
httpSampler.setPort(1111);
httpSampler.setPath("/");
httpSampler.setMethod("POST");
httpSampler.addNonEncodedArgument("","{data:{ \"email\" :
\"xx#gmail.com\",there are more values in the body"}]}","" );
httpSampler.setPostBodyRaw(true);
httpSampler.setFollowRedirects(true);
httpSampler.setAutoRedirects(false);
httpSampler.setUseKeepAlive(true);
httpSampler.setDoMultipartPost(false);
httpSampler.setProperty(TestElement.TEST_CLASS,
HTTPSamplerProxy.class.getName());
httpSampler.setProperty(TestElement.GUI_CLASS,
HttpTestSampleGui.class.getName());
//Header Manager
HeaderManager headerManager = new HeaderManager();
headerManager.setName(JMeterUtils.getResString("header_manager_title"));
headerManager.add(new Header("abcs", "asdasd"));
headerManager.add(new Header("dsferdg", "ertret"));
headerManager.setProperty(TestElement.TEST_CLASS,
HeaderManager.class.getName());
headerManager.setProperty(TestElement.GUI_CLASS,
HeaderPanel.class.getName());
httpSampler.setHeaderManager(headerManager);
//Loop Controller
LoopController loopController = new LoopController();
loopController.setLoops(1);
loopController.setFirst(true);
loopController.addTestElement(httpSampler);
loopController.setProperty(TestElement.TEST_CLASS,
LoopController.class.getName());
loopController.setProperty(TestElement.GUI_CLASS,
LoopControlPanel.class.getName());
loopController.initialize();
//Thread Group
ThreadGroup threadGroup = new ThreadGroup();
threadGroup.setName("Sample Thread Group");
threadGroup.setNumThreads(1);
threadGroup.setRampUp(1);
threadGroup.setSamplerController(loopController);
threadGroup.setProperty(TestElement.TEST_CLASS,
ThreadGroup.class.getName());
threadGroup.setProperty(TestElement.GUI_CLASS,
ThreadGroupGui.class.getName());
//Test Plan
TestPlan testPlan = new TestPlan("Create JMeter Script From Java Code");
testPlan.setProperty(TestElement.TEST_CLASS, TestPlan.class.getName());
testPlan.setProperty(TestElement.GUI_CLASS,
TestPlanGui.class.getName());
testPlan.setUserDefinedVariables((Arguments) new
ArgumentsPanel().createTestElement());
HashTree threadGroupHashTree = testPlanTree.add(testPlan, threadGroup);
threadGroupHashTree.add(httpSampler,headerManager);
//Construct Test Plan from previously initialized elements
testPlanTree.add("testPlan", testPlan);
testPlanTree.add("loopController", loopController);
testPlanTree.add("threadGroup", threadGroup);
testPlanTree.add("httpSampler", httpSampler);
testPlanTree.add("headerManager", headerManager);
Summariser summer = null;
String summariserName = JMeterUtils.getPropDefault("summariser.name",
"summary");
if (summariserName.length() > 0) {
summer = new Summariser(summariserName);
}
ResultCollector resultcoll = new ResultCollector();
testPlanTree.add("resultcoll", resultcoll);
resultcoll.setFilename("C:/Users/xxx");
SampleSaveConfiguration saveConfiguration = new
SampleSaveConfiguration();
saveConfiguration.setAsXml(true);
saveConfiguration.setCode(true);
saveConfiguration.setLatency(true);
saveConfiguration.setTime(true);
saveConfiguration.setTimestamp(true);
resultcoll.setSaveConfig(saveConfiguration);
//Store execution results into a .jtl file, we can save file as csv also
String reportFile = "C:/Users/xxx.jtl";
String csvFile = "C:/Users/xxx.csv";
ResultCollector logger = new ResultCollector(summer);
logger.setFilename(reportFile);
ResultCollector csvlogger = new ResultCollector(summer);
csvlogger.setFilename(csvFile);
testPlanTree.add(testPlanTree.getArray()[0], logger);
testPlanTree.add(testPlanTree.getArray()[0], csvlogger);
//save generated test plan to JMeter's .jmx file format
SaveService.saveTree(threadGroupHashTree, new
FileOutputStream("C:\\Users\read.jmx"));
// Run Test Plan
jmeter.configure(testPlanTree);
jmeter.run();
/*System.out.println("Test completed. See " + JMeterHome + slash +
"report.jtl file for results");
System.out.println("JMeter .jmx script is available at " + jmeterHome +
slash + "jmeter_api_sample.jmx");*/
System.exit(0);
}
}
I have used this code to configure the jmeter POST request and to add the body data but the request body appears to be null when I check the response.
Maybe you should be adding arguments to httpSampler, and not to the sampler, something like:
HTTPSamplerProxy httpSampler = new HTTPSamplerProxy();
httpSampler.setDomain(xx);
httpSampler.setPort(xx);
httpSampler.setPath("xx");
httpSampler.setMethod("xx");
httpSampler.addNonEncodedArgument("body", body, "");
If you are building JMeter test from Java code using JMeter API check out Five Ways To Launch a JMeter Test without Using the JMeter GUI and jmeter-from-code repository for some snippets you could re-use.

How to run Spring Shell scripts in a JUnit test

I have a Spring Shell-based application and a couple of scripts. Is there an easy way to run the scripts in a JUnit test such that a test fails, if some exception/error occurs during the execution of the script?
The purpose of the tests is to make sure that all correct scripts run without errors.
Update 1:
Here's a little helper class for running scripts in JUnit:
import org.apache.commons.io.FileUtils;
import org.springframework.shell.Bootstrap;
import org.springframework.shell.core.CommandResult;
import org.springframework.shell.core.JLineShellComponent;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static org.fest.assertions.api.Assertions.*;
public class ScriptRunner {
public void runScript(final File file) throws IOException
{
final Bootstrap bootstrap = new Bootstrap();
final JLineShellComponent shell = bootstrap.getJLineShellComponent();
final List<String> lines = FileUtils.readLines(file);
for (final String line : lines) {
execVerify(line, shell);
}
}
private void execVerify(final String command, final JLineShellComponent shell) {
final CommandResult result = shell.executeCommand(command);
assertThat(result.isSuccess()).isTrue();
}
}
You can create an instance of Bootstrap, get the shell out of it and then executeCommand() (including the shell command) on it.
You may be interested in what is done in Spring XD for this: https://github.com/spring-projects/spring-xd/blob/master/spring-xd-shell/src/test/java/org/springframework/xd/shell/AbstractShellIntegrationTest.java (although there are a lot of XD specific details)

Categories

Resources