You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 16 Next »

Building JMeter plug-in with Eclipse

Targetted to Eclipse 3.1 and JMeter 2.1 trunk version. JMeter isn't designed to be edited from Eclipse IDE, so some work has to be done before we get wheels running.

Building JMeter from sources with Eclipse

It's useful to have JMeter Eclipse project in hand, since you need to do debugging and possible bug fixing of JMeter.

  1. Check out JMeter trunk from Subversion

2. Set up jmeter-trunk project

  • Let Eclipse internal compiler handle the building of JMeter, instead of relying on JMeter's own Ant build files. When Eclipse handles building, development work goes more smoothly.
  • Source build paths:
  • src/protocol/ftp
  • test/src
  • src/protocol/http
  • src/protocol/java
  • src/protocol/jdbc
  • src/protocol/tcp
  • src/monitor/components
  • src/monitor/model
  • src/components
  • src/core
  • src/examples
  • src/functions
  • src/htmlparser
  • src/jorphan
  • src/junit
  • src/reports
    • Exclude following files from building
      • They have missing dependencies and are related to HTTP security which you are not probably interested in
      • org/apache/jmeter/util/JsseSSLManager.java
      • org/apache/jmeter/util/keystore/DefaultKeyStore.java
      • org/apache/jmeter/util/keystore/PKCS12KeyStore.java
    • Add libraries
      • All jar files under lib/ folder
    • To make log4j logging to Eclipse console work, you need to comment out some code. Read more notes about this below. Class is org.apacha.jmeter.jorphan.logging.LoggingManager
	public static void initializeLogging(Properties properties) {
		if (logManager == null) {
			logManager = new LoggingManager();
		}

		/* This following code caused me to lost 3 hours of working time 
		 * and now I am extra frustrated
		 
		setFormat(properties);

		// Set the top-level defaults
		setTarget(makeWriter(properties.getProperty(LOG_FILE, "jmeter.log"), LOG_FILE));
		setPriority(properties.getProperty(LOG_PRIORITY, "INFO"));

		setLoggingLevels(properties);
		// now set the individual categories (if any)
		 * 
		 */

		setConfig(properties);// Further configuration
		
	}
  • Now Eclipse should build JMeter without errors (stop icons in source tree)

Setting up plug-in project

This project will build your custom components and launch JMeter so that it will find them.

  1. Set up your custom plug-in project
    • Create a new Java project
    • Add jmeter-trunk to project dependencies
    • Create bin/ and src/ folders
    • Create jmeter.properties in the bin/
      • This defines where JMeter internal class loader looks for classes
      • It should look like this
# JMeter uses case sensitive string matching to test these paths against class path.
# This is very bad since paths must be *exactly* here as they appear in Java classpath.
# Hopefully this will be fixed in the future versions. Note Windows needs to escape \ character as \\.

# Add JMeter output folder and our plug-in output folder to paths from which 
# plug-ins are searched
search_paths=C:\\xxx\\jmeter-trunk\\bin;.
			 .

  • Create log4j.conf in src/
log4j.rootLogger=debug, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

2. Setting up a JMeter launcher

  • Set working directory to bin/ in your project
    • JMeter is hard coded to look up jmeter.properties in the launch folder
    • E.g. ${workspace_loc:SIPPerformanceStresser/bin}
  • Copy lib/ from jmeter-trunk to your plug-in project root
    • JMeter is hard coded to look up jars from ../lib
  • Main class: org.apache.jmeter.NewDriver

Creating components

JMeter 2.x uses its internal TestBean-framework for adding new components.

For each component you need

  1. An element class which interits from [TestElement, ConfigurationElement, XXXElement] and implements [TestBean] interface. [TestBean] interface marks classes which JMeter plug-in class loader loads automatically.

2. Each TestBean class needs BeanInfoSupport class whichs describes the properties of the element class 3. Properties file which gives out user interface strings for properties

Example:

package fi.xxx.jmeter.sip.core;

import org.apache.jmeter.samplers.AbstractSampler;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testbeans.TestBean;

public class SIPReceiver extends AbstractSampler implements TestBean {

	public SampleResult sample(Entry e) {
		return null;
	}

}

  • fi.xxx.jmeter.sip.core.SIPReceiverBeanInfoSupport extends BeanInfoSupport
package fi.xxx.jmeter.sip.core;

import java.beans.PropertyDescriptor;

import org.apache.jmeter.config.CSVDataSet;
import org.apache.jmeter.testbeans.BeanInfoSupport;

public class SIPReceiverBeanInfoSupport extends BeanInfoSupport {
	
	public SIPReceiverBeanInfoSupport() {
		super(SIPReceiver.class);
		
		createPropertyGroup("sip_receiver", new String[] { "filename", "variableNames", "delimiter" });
		PropertyDescriptor p = property("filename");
		p.setValue(NOT_UNDEFINED, Boolean.TRUE);
		p.setValue(DEFAULT, "");
		p.setValue(NOT_EXPRESSION, Boolean.TRUE);
		p = property("variableNames");
		p.setValue(NOT_UNDEFINED, Boolean.TRUE);
		p.setValue(DEFAULT, "");
		p.setValue(NOT_EXPRESSION, Boolean.TRUE);
		p = property("delimiter");
		p.setValue(NOT_UNDEFINED, Boolean.TRUE);
		p.setValue(DEFAULT, ",");
		p.setValue(NOT_EXPRESSION, Boolean.TRUE);
	}
}


  • fi/xxx/jmeter/sip/core/SIPreceiver.properties
displayName=SIP Receiver
sip_receiver.displayName=Configure SIP receiver
filename.displayName=Filename
filename.shortDescription=Name of the file (within your supporting file directory) that holds cvs data
variableNames.displayName=Variable Names (comma-delimited)
variableNames.shortDescription=List your variable names in order to match the order of columns in your csv data.  Separate by commas.
delimiter.displayName=Delimiter (use '\\t' for tab)
delimiter.shortDescription=Enter the delimiter ('\\t' for tab)

Notes

Faulty jorphan logging launcher

I wasted 4 hours trying to get Jorphan logging to work. Jorphan overrides log4j normal configuration mechanism, but does it badly, making usage of custom log4j settings impossible. Specifically initializeLogging always overrides previous settings with its own default settings.

  1. There is one missing dependency which causes start-up failure with message Caused by: java.lang.NoClassDefFoundError: org/apache/avalon/excalibur/i18n/ResourceManager if you try to configure logger. Get the jar file from http://mirrors.bevc.net/apache/excalibur/excalibur-i18n/binaries/ and place it to lib/

2. Even after placing a correct logging file through jmeter.properties settings you get this

org.apache.avalon.framework.configuration.ConfigurationException: No log targets configured for the root logger.
	at org.apache.avalon.excalibur.logger.LogKitLoggerManager.setupLoggers(LogKitLoggerManager.java:531)
	at org.apache.avalon.excalibur.logger.LogKitLoggerManager.configure(LogKitLoggerManager.java:407)
	at org.apache.jorphan.logging.LoggingManager.setConfig(LoggingManager.java:148)
	at org.apache.jorphan.logging.LoggingManager.initializeLogging(LoggingManager.java:114)
	at org.apache.jmeter.util.JMeterUtils.getProperties(JMeterUtils.java:133)
	at org.apache.jmeter.JMeter.initializeProperties(JMeter.java:327)
	at org.apache.jmeter.JMeter.start(JMeter.java:242)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.apache.jmeter.NewDriver.main(NewDriver.java:161)

My head was already hurting so badly that I didn't want to debug the problem further. The JMeter logging code had several deprecated non-func historic layers confusing poor debuggers.

  • No labels