skip to content

A JMeter plan using bzm - Concurrency Thread Group will not open on a fresh install. Why?

level: seniorimportance: should knowfreq 49%

answer

  1. Look at the raw XML tag name
  2. No alias exists for a third-party class
  3. Nothing is salvaged from a failed parse
  4. The console message names the file

basics

~10 s

The .jmx stores that element under its fully-qualified class name, and a stock install has no such class. JMeter cannot resolve it, so the whole plan fails to load rather than losing one element.

solid answer

~50 s

Apache JMeter writes short XML tags for its own elements because `bin/saveservice.properties` maps an alias to each class. Third-party elements have no alias, so the `.jmx` names them in full: the group is written as `<com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup ... >`. On loading, JMeter asks XStream to resolve that tag; with the `jpgc-casutg` jar absent the class is not on the classpath, the resolution fails, and `SaveService.readTree` rethrows it as `IllegalArgumentException: Problem loading XML from:'<path>'`. The failure is total, not partial - there is no salvaged tree with the group dropped. In the GUI you get an error dialog - titled simply *Error* - carrying that same `Problem loading XML from:'<path>'` text; the words *Unexpected error* appear only in `jmeter.log`. Under `jmeter -n` the console prints `Error in NonGUIDriver java.lang.IllegalArgumentException: Problem loading XML from:'...'` and the run never starts, so no results file appears. The fix is to make the add-on present at the pinned version before the plan is opened.

go deeper

for a junior

Recall that a plugin element is stored in the .jmx by its class name, so a plan that uses one needs that jar wherever the plan is opened.

for a middle

Explain that resolution happens during deserialisation, which is why the load fails whole rather than dropping the element, and quote the shape of the error message.

for a senior

Diagnose it from the console line alone under jmeter -n, then fix it by installing the pinned add-on version rather than the newest, and check the other plans for the same dependency.

for a principal

Set the rule that makes this class of failure impossible for the team: what is inventoried from the plans, what is pinned, and where that check runs before a load-bearing run is scheduled.

## What the .jmx actually records A JMeter test plan is XStream-serialised XML. For Apache's own elements the tag is short, because `bin/saveservice.properties` maps an alias to a class - `ThreadGroup=org.apache.jmeter.threads.ThreadGroup`, `OpenModelThreadGroup=org.apache.jmeter.threads.openmodel.OpenModelThreadGroup`, and so on. That file is explicitly for JMeter's own classes, and it has no entry for anything a third party ships. So when the plan is saved, a plugin element is written under its fully-qualified class name, three times over - as the tag, as `guiclass` and as `testclass`: ```xml <com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup guiclass="com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroupGui" testclass="com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup" testname="bzm - Concurrency Thread Group" enabled="true"> ``` The same is true of `kg.apc.jmeter.threads.SteppingThreadGroup` and `kg.apc.jmeter.threads.UltimateThreadGroup`. Grepping a plan for `com.blazemeter` and `kg.apc` is therefore an exact inventory of the add-on classes it needs. ## Why the whole file fails, not one element JMeter wraps XStream's mapper so that a tag is first looked up in the alias table and, failing that, treated as a class name. With no alias and no class, resolution throws, and `SaveService.readTree` catches `CannotResolveClassException`, `ConversionException` and `NoClassDefFoundError` together and rethrows a single `IllegalArgumentException` whose message begins `Problem loading XML from:'<absolute path>'`. There is no partial-load path: the deserialiser never returns a tree, so nothing downstream gets a chance to skip the unknown node. That is the point worth internalising. A missing add-on is not a degraded run with one element ignored; it is a plan you cannot even inspect. ## The two symptoms you will actually see | Where | What you see | |---|---| | GUI | an error dialog titled *Error* carrying the `Problem loading XML from` message (`jmeter.log` adds `Unexpected error.`); the tree stays as it was | | `jmeter -n -t plan.jmx -l results.jtl` | stdout carries `Error in NonGUIDriver java.lang.IllegalArgumentException: Problem loading XML from:'...'`, the engine never starts and `results.jtl` is never written | The non-GUI shape is the one that bites, because the job looks like a test that failed rather than a machine that is missing a jar. A pipeline that only checks for a results file will report the run as broken without saying why. ## Getting the add-on onto the machine The element lives in one jar, `jmeter-plugins-casutg`, which belongs in `lib/ext`. Three routes reach the same place: 1. **Plugins Manager GUI** - install the manager jar into `lib/ext`, restart, then use the entry it adds to the **Options** menu; the *Available* tab lists **Custom Thread Groups**, and the *Review Changes* pane shows the jars it will pull, including dependencies. 2. **`PluginsManagerCMD install jpgc-casutg=3.1.1`** - the `id=version` form pins one exact version rather than taking whatever is newest. 3. **`PluginsManagerCMD install-for-jmx plan.jmx`** - reads the plan and installs the plugins whose component classes it references, which is the shortest path from *this plan will not open* to *this plan opens*. `PluginsManagerCMD` itself needs the `cmdrunner` jar in `lib` and its launcher script in `bin`, which the manager can generate. ## Making the failure loud early - Grep every checked-in `.jmx` for `kg.apc` and `com.blazemeter` and keep the resulting list of plugin ids next to the plans. - Verify the add-on before the plan is loaded rather than after: `PluginsManagerCMD status` names installed plugins and their versions. - Treat the version as part of the plan's contract - the `id=version` form exists because *installed* and *installed at the version this plan was authored against* are different statements.

  • How can you tell from a JMeter .jmx alone which add-ons it needs?
    Read the element tags. Apache elements appear under short aliases from `bin/saveservice.properties`; third-party elements appear as fully-qualified class names, so grepping for package prefixes such as `kg.apc` and `com.blazemeter` lists exactly the plugin classes the file will demand at load time.
  • Why does JMeter not just skip an element whose class it cannot resolve?
    Because resolution happens inside XStream while the document is being deserialised, before any tree exists. `SaveService.readTree` catches the resolution failure and rethrows it as an `IllegalArgumentException`, so the load returns no tree at all rather than a tree with a hole in it.
  • Which Plugins Manager command turns a plan you cannot open into one you can?
    `PluginsManagerCMD install-for-jmx <plan.jmx>` inspects the plan and installs the plugins whose component classes it references. Where you already know the dependency and want it fixed, `PluginsManagerCMD install jpgc-casutg=3.1.1` pins the exact version instead of taking the newest.

saying these in an interview costs you the question

  • Expects JMeter to drop the unknown element and continue
  • Blames the test plan XML for being corrupt
  • Thinks a plugin jar is only needed where the test runs
  • Assumes any version of the add-on will do
  • Looks for a results file to diagnose a load failure