Calling scala method with a gatling scenario

Hi everybody !

I posted on stackoverflow but it seems it’s a better approach to ask questions here. I really appreciate Gatling’s team reactivity and help !

So, I have a simple function like :

object Actions { def myAction() { //do some stuff } }

Is there a way to use this method as a scenario ? Like :

val scn = scenario("My scenario").exec(Actions.myAction())

This code doesn’t compile but I don’t understand why… it seams exec is waiting for a chain / scenario builder (or a validation object).

Perhaps I’ve not enough scala skills for understanding key concepts in using Gatling…

Thks a lot !

it seams exec is waiting for a chain / scenario builder (or a validation

object).

Yep, exactly. And here, you don't return anything (you use the deprecated
procedure style).

procedure style:
def myAction() { //do some stuff }

equivalent to (proper method style, return Unit, ie nothing):
def myAction(): Unit = { //do some stuff }

What you should be doing:
def myAction(): ChainBuilder = { //do some stuff }

or (letting compiler infer return type)
def myAction() = { //do some stuff }

It seems you're trying to write some Scala code without any Scala very
basics. if so, you really should have a look at the first chapters from
Twitter's Scala school: Scala School

Thks again for your help, in fact I wrote a “void” procedure because I don’t know what I have to return :slight_smile:

My function is now :

`
object Actions {

def notifyAllCompanies():ChainBuilder = {
var i:Int = 0;
for(i ← 0 to FeederUtils.companiesIterator - 1) {
var currentCompany = FeederUtils.activeCompanies(FeederUtils.companiesIterator)

if (FeederUtils.companiesIterator < FeederUtils.activeCompanies.size - 1) {
FeederUtils.companiesIterator+=1
} else {
FeederUtils.companiesIterator=0
}
Actions.notifyCompanyEntries(currentCompany(“activeCompanyName”));
wait(2000);
}

}

`

In adding ChainBuilder return type I have a type mismatch error on “<-” operator.

It seems you’re trying to write some Scala code without any Scala very basics. if so, you really should have a look at the first chapters from Twitter’s Scala school: https://twitter.github.io/scala_school/

You’re right, I read first lines of this tutorial but it seems it’s not enough :slight_smile: Sorry for asking beginners questions, I’ll try to read more carefully this guide !

Your for loop doesn’t yield anything.

No offense, but you’re really trying to jump right into the code while you don’t know some basics about the language. So you’re trying to write some random Java stuff and crossing fingers that it might somehow work.

Hold your horses, read some Scala tutorial and Gatling advanced documentation for a few hours and you’ll be set!

I’m reading the doc, don’t worry :slight_smile: But I’m very surprised… why adding “ChainBuilder” return type shows an error with my loop ?

It seems that this notation is correct : I founded it here : http://www.tutorialspoint.com/scala/scala_for_loop.htm

For another script its working fine…

“Your for loop doesn’t yield anything.”

That’s why I wrote :

Thks again for your help, in fact I wrote a “void” procedure because I don’t know what I have to return :slight_smile:

I’m looking for more information about ChainBuilder. I don’t understand how exec works.

I’m not here demanding all-in-one solutions :wink:

Gatling DSL components are immutable builders that are resolved once when
the simulation is loaded. The build result is the actual scenario.

ChainBuilder
<https://github.com/gatling/gatling/blob/master/gatling-core/src/main/scala/io/gatling/core/structure/ChainBuilder.scala>
wraps ActionBuilders, which are the steps. Amongst others, you can chain a
ChainBuilder with another ChainBuilder, or an Action, with the exec method.

I read and read again your answer. I went to https://github.com/gatling/gatling/blob/master/gatling-core/src/main/scala/io/gatling/core/structure/Execs.scala to have a better understanding of Exec but it has no effect on my little brain :slight_smile:

Perhaps my approach is too Java-oriented but I imagine that exec is waiting for a specific method to call and that ChainBuilder is a kind of interface. I read scala school first chapters and no idea comes to me… is there a way to encapsulate scala code into ChainBuilder or I have to use exclusively gatling stuff ?

What I want to do is simple : I have two csv files. For each row of the first file, I want to call a method that parses second file and execute some code, knowing first file row value.

“notifyAllCompanies” parses first file and calls “notifyCompanyEntries” with row value. I don’t think this it is possible to encapsulate both treatments into gatling builder… am I wrong ? In addition, I thought this could be too spaghetti code.

Perhaps my approach is too Java-oriented but I imagine that exec is waiting for a specific method to call

Absolutely not. exec takes an ActionBuilder or ChainBuilder parameter, period!

Read about the builder pattern: http://www.javaworld.com/article/2074938/core-java/too-many-parameters-in-java-methods-part-3-builder-pattern.html

Perhaps my approach is too Java-oriented

No. Your approach is imperative programming oriented, based on mutability, and your problem lies here. It has nothing to do with the language but with the way your using it.

Thanks for builder pattern explanation : I think I understand theory… so I have to create a custom ActionBuilder ? If I understand I have to write :

class Test extends ActionBuilder {
def testMethod(): ActionBuilder = {
//Don't know how to return instance
}
}

Then using Test.testMethod() with exec ? I’m looking about abstract trait concept.

I think the only solution for now is that you share your code so I can fix it.

My class seems like that (I removed useless data for your comprehension) :

`
class MyClass extends Simulation {
val machine = “machineName”

val baseUri = “http://”+machine+"/baseUri";
val uri="/wsdlPort"

val httpProtocol = http
.baseURL(baseUri)
.disableWarmUp

/**

  • CSV File record vectors
    */
    object FeederUtils {
    val socEntries = csv(“entries.csv”).records

val activeCompanies = csv(“companies.csv”).records
var companiesIterator = 0;
}

object Actions {

/**

  • For each company, calls notifyCompanyEntries
    */
    def notifyAllCompanies() {
    var i = 0;
    for(i ← 0 to FeederUtils.companiesIterator - 1) {
    var currentCompany = FeederUtils.activeCompanies(FeederUtils.companiesIterator)

if (FeederUtils.companiesIterator < FeederUtils.activeCompanies.size - 1) {
FeederUtils.companiesIterator+=1
} else {
FeederUtils.companiesIterator=0
}
Actions.notifyCompanyEntries(currentCompany(“activeCompanyName”));
wait(2000);
}

}

/**

  • Notifies all entries for a company (reads entries vector)
    */
    def notifyCompanyEntries(companyName: String) {
    foreach(FeederUtils.socEntries, “record”) {
    exec(flattenMapIntoAttributes("${record}"))
    .exec({session => session.set(“codeSociete”, companyName)})
    .exec(http(“Notify ${codeEntree}”)
    .post(uri)
    .body(StringBody(""“content”""))
    .header(“Content-Type”, “text/xml;charset=UTF-8”)
    .header(“SOAPAction”,“DCInterfaceRecherchePrix_ws_v1_rechercherPrix_Binder_rechercherPrix”)
    .basicAuth(“Administrator”,“manage”)
    )}
    }

}

/**

  • Scenario : one user first…
    */
    val scn = scenario(“Soc test”).exec() //TODO ?

setUp(
scn.inject(atOnceUsers(1)).protocols(httpProtocol)
)

}

`

What is “wait”? Why don’t you use pause?

OMG, wait is indeed Object.wait!!!

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._
import scala.concurrent.duration._

class MyClass extends Simulation {
val machine = “machineName”

val baseUri = “http://” + machine + “/baseUri”;
val uri = “/wsdlPort”

val httpProtocol = http
.baseURL(baseUri)
.disableWarmUp

/**

  • CSV File record vectors
    */
    object FeederUtils {
    val socEntries = csv(“entries.csv”).records

val activeCompanies = csv(“companies.csv”).records
}

object Actions {

/**

  • For each company, calls notifyCompanyEntries
    */
    val notifyAllCompanies =
    for (activeCompany ← FeederUtils.activeCompanies)
    yield Actions.notifyCompanyEntries(activeCompany(“activeCompanyName”)).pause(2000)

/**

  • Notifies all entries for a company (reads entries vector)
    */
    def notifyCompanyEntries(companyName: String) = {
    foreach(FeederUtils.socEntries, “record”) {
    exec(flattenMapIntoAttributes("${record}"))
    .exec({ session => session.set(“codeSociete”, companyName) })
    .exec(http(“Notify ${codeEntree}”)
    .post(uri)
    .body(StringBody(""“content”""))
    .header(“Content-Type”, “text/xml;charset=UTF-8”)
    .header(“SOAPAction”, “DCInterfaceRecherchePrix_ws_v1_rechercherPrix_Binder_rechercherPrix”)
    .basicAuth(“Administrator”, “manage”))
    }
    }

}

/**

  • Scenario : one user first…
    */
    val scn = scenario(“Soc test”).exec(Actions.notifyAllCompanies)

setUp(scn.inject(atOnceUsers(1)).protocols(httpProtocol))
}

I wrote wait but I couldn’t test it because of my calling problem, so perhaps it was a bad suggestion from eclipse… :slight_smile:

Thanks for your code suggestions, I will analyze it tomorrow. How can we use scala methods with inheritance ?

  • After some workaround -

Thanks for helping, script is not still working but you gave me some clues.

I have a stack overflow error because loop doesn’t break, I don’t know why. I’m working on it.

I don’t understand return type inference : adding “=” lets compiler infer return type, it seems kind of magic because I’m never using ChainBuilder ! So at execution time, what object is returned and how exec uses it ?

Anyway, one again thanks for helping. I really appreciate. I thought it will be easier to understand scala basics and to use it with gatling.

More precision :

My CSV file contains :

activeCompanyName valA valB

During debugging, for loop never ends and & behavior seems strange :

1 val notifyAllCompanies = 2 for (activeCompany <- activeCompanies) 3 yield Actions.notifyCompanyEntries(activeCompany("codeSociete"))

Line 2 is executed 2 times, then line 3 one time… and activeCompany contains each time the first record.

I don't understand return type inference : adding "=" lets compiler infer
return type

No, it defines a method (returning something) instead of a procedure
(returning nothing)

it seems kind of magic because

Magic doesn't exist in computer science.

Anyway, one again thanks for helping. I really appreciate. I thought it
will be easier to understand scala basics and to use it with gatling.

Use the DSL first. Keep things simple. Then once you're proficient with the
basics, learn Scala basics and customize.
This introduction looks fine:
http://www.scala-lang.org/docu/files/ScalaTutorial.pdf