2

I am using this method to generate a random token in Scala:

  def randomString(alphabet: String)(n: Int): String =
    Stream.continually(Random.nextInt(alphabet.size)).map(alphabet).take(n).mkString

I use this method to generate a default value for a form:

  val userForm = Form(
    mapping(
      "token" -> default(text, (randomString("0123456789abcdef")(40))),
      "username" -> optional(text),
      "email" -> email,
      "password" -> nonEmptyText,
      "gender" -> nonEmptyText
    )(User.apply)(User.unapply)
  )

Why do I always get the same token when running this code?

2
  • 1
    If you execute randomString as written, it generates random tokens. Have you tried it in isolation? Commented May 23, 2014 at 22:41
  • Are you reusing the userForm? Is so then that's your problem. default takes (Mapping[A],A) not (Mapping[A],=>A), so you only generate one token and then use it every time. I've put this as an answer, but this might not be your problem. Commented May 24, 2014 at 1:10

2 Answers 2

4

Your randomString works as expected. The problem is with how you're using it.

The default[A](mapping: Mapping[A], value: A) method is getting a value from randomString(...)(...) and that value stays with the Form that you've just created. So userForm will use the same random token every time it has use the default.

Were you to create a new Form every time then you would not have this problem. This would be as easy as changing val to def. But there is certainly a better way to do it.


The alternative would be to create your own Mapping that acts default but takes a thunk as its second argument.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @ggovan. userForm is defined in my Application controller. This code runs in Play framework. It is being called in one of my Actions: "userForm.bindFromRequest.fold("...
And you are correct: the code for generating the random value is called only once. The question is: how do I assign a random value to a form field.
As I've added to my answer, make your own mapping. You could probably just copy most of it from the source of the default method in Forms.
0

scala.util.Random is using java.util.Random for generating random numbers. ju.Random is using 48 bit seed for generating random numbers. If you create two instances of Random with same seed (as in your case) they'll return same sequence of random numbers.

You should create Random class with non default constructor that takes seed number. For ex. you can use currentTimeMillis for seed.

1 Comment

But no seed is being used here. This is using the companion object, which uses the zero-args constructor of scala Random and java Random. And the zero-args constructor of java Random says sets the seed of the random number generator to a value very likely to be distinct from any other invocation of this constructor.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.