Using ScalaJS with async/promises/futures

1,985 views
Skip to first unread message

SemanticBeeng .

unread,
Jan 11, 2015, 11:33:44 PM1/11/15
to scal...@googlegroups.com
Hi,

I am looking to use ScalaJS to develop a business API called from a web application using Durandal and Knockout. The command layer calling the API will use promises/futures to communicate with the rest of the application.

(more elaborate architectural description at the end to qualify questions below)

So am trying to determine what is the best way to write this layer driven by "executable specifications".

Found some references to ScalaJS support for async/promises but cannot quite tell which way to go.
Below I ask some questions to better understand the plans for ScalaJS, utest and seek some recommendations.

1. "The Jasmine test framework is not a good testing framework for Scala.js code, and is being removed in 0.6.x."


Q: Where can I learn more about this and understand why Jasmine is bad for ScalaJS testing?
JavaScript has impressive support for testing async code with promises: chai as promised, sinon.js, jasmine, mocha, etc 

What does "bad" mean in terms of one being able to use this existing support?

-------------------------------------------------------

2. utest seems to support async tests 


Q: Does utest mean to provide full support for promises?

Would one be able to use native JavaScript promise support to test JSExported shared APIs?
From utests? 
From other kinds of tests?

Or does "bad" in the above definition means that this is not a good idea?

-------------------------------------------------------

3. ScalaJS has support for scala Futures (scala.concurrent.Future)

References 

Q: Does utest mean to support testing such APs?

-------------------------------------------------------
4. Autowire also uses Futures.

Q: Does utest support testing such APIs? Any examples handy?

Finally

Q: Can you please suggest some material to better understand how to BDD this ScalaJS based command layer that specifies the semantics of the shared business API given that it needs to be specified with "promises" (see [1])?

=======

(context for questions)

The overall architecture uses CQRS and the calls to this business API will be using some form of command pattern. 

At this level it is customary to use "promises". 
Durandal and the rest of the application can use Q.JS (https://github.com/kriskowal/q) because they are a more standard implementation (https://blog.domenic.me/youre-missing-the-point-of-promises/).

I could write this whole command layer in ScalaJS or in TypeScript and call JSExported methods from the business API.

Regardless, I need this command layer to return Q.js promises to the rest of the application. [1]

To implement this layer I am considering using Autowire but Play! makes much of it unnecessary. 
Thinking to reuse the shared API to wrap the JavaScript routes generated by Play! instead. 
This is supposed to provide even better typesafety than AutoWire because the Ajax calls itself will no longer be handcrafted like with AutoWire.

(end of context)


Justin du coeur

unread,
Jan 12, 2015, 7:54:41 AM1/12/15
to SemanticBeeng ., scal...@googlegroups.com
I'll let Haoyi tackle most of this, since he knows it better, but one comment from experience:

On Sun, Jan 11, 2015 at 11:33 PM, SemanticBeeng . <semanticbeen...@gmail.com> wrote:
To implement this layer I am considering using Autowire but Play! makes much of it unnecessary. 
Thinking to reuse the shared API to wrap the JavaScript routes generated by Play! instead. 
This is supposed to provide even better typesafety than AutoWire because the Ajax calls itself will no longer be handcrafted like with AutoWire.

This is the approach I started with -- mainly focused on my existing Play infrastructure, and adding a bit of Autowire on top of it -- but I've wound up switching to exactly the other way.  After working with it for a while, I've found that maintaining Autowire APIs is significantly easier than doing so with Play, and I spent less effort mucking with the translations.  Moreover, my Autowire API is wired much more *deeply* into my server: I spent a while writing the plumbing in Play, but now just ignore it and focus on connecting my ScalaJS front end directly to my Akka actors in the back end via Autowire.

Autowire isn't a panacea -- it does have some specific limitations in terms of the classes you can represent and such.  But I've found that those limitations are generally fine when I'm thinking in API terms, and it mostly just works now that the plumbing is done... 

SemanticBeeng

unread,
Jan 12, 2015, 8:49:39 AM1/12/15
to scal...@googlegroups.com, semanticbeen...@gmail.com
Thanks, Justin.

Will think this over then,

Here's how I look at AutoWire

1. On the client I still have to worry about handcrafting the Ajax call: urls, get, post, etc
With PLay! generated routers this is done for me

  override def doCall(req: Request): Future[String] = {

    print(req.path)
      url = "/api/" + req.path.mkString("/"),
      data = upickle.write(req.args)
    ).map(_.responseText)
  }

2. On the server 

        post {
          path("api" / Segments) { s =>
            extract(_.request.entity.asString) { e =>
              complete {
                AutowireServer.route[CustomerMgmtService](Server)(
                  autowire.Core.Request(s, upickle.read[Map[String, String]](e))
                )
              }
            }
          }
        }

is handled by Play! 

But of course you know this.

Maybe you can share some examples for my education?

Are you saying that you are not calling Play! controllers much but communicate over Akka between your Scala and ScalaJS parts of the app?
So are you using ScalaJS actors then?

If I do not use Akka but controllers then would you still say it makes more sense to use AutoWire?

With what I had in mind I'd do nothing more than just (somehow) add the strongly typed interface to the JavaScript routes generated by Play!
I assume there is a way to do this nicely with ScalaJS's ability to use native JavaScript but have not tried this yet.

So I would not need Autowire at all but achieve the same typesafety AutoWire brings.
I like AutoWire but do not see why I would use it with Play!. I only need the typesafety AutoWire promotes.

Please share more insights.

Thanks
Nick


Justin du coeur

unread,
Jan 12, 2015, 9:20:00 AM1/12/15
to SemanticBeeng, scal...@googlegroups.com
So the question I eventually realized I should be focusing on was that my *real* entry point was very different from where the Play! architecture had led me to.  That is, I had my big Akka back end, with Play sitting on top of it -- requests would come into Play via AJAX, Play would unmarshall them and feed them into the correct Akka actors, those Actors would return the answer and Play would remarshall it.  From that POV, Autowire didn't add much.

But what I gradually realized was that the *real* API was the Actor, not Play.  So I would up instead adding one new entry point to Play (kind of -- see below), which deserialized the request but did *not* route it.  Instead, that entry point is designed to take just enough information to find the right Actor, and it passes the deserialized Autowire Request to that Actor.  The *Actor* then creates a one-off object to handle the request, and routes into that object.

This took a while to set up and get right (gradually evolved over a couple of weeks), but now that I've got it, it's a thing of beauty -- when I want to add a new entry point, or edit an existing one, I just edit the API trait and the implementing object, and It Just Works.  Even adding whole new APIs is proving fairly easy: I just add another implementing class and another routing pathway, which takes maybe two minutes.

Even more significantly: when I moved away from doing the plumbing through Play, and stopped having to do lots of fiddly serialization of my business objects, the amount of code dropped *dramatically*.  The new versions of my API implementations, using Autowire, are running about a third the size of my old Play ones, simply because the connection is tighter and more natural.  Since it's all just Scala at all levels, without having to think about JSON at all (except as an under-the-hood implementation detail), it's much easier.

YMMV -- this approach is very well-suited to my architecture, where the user is primarily talking to a single interface Actor that serves as the gateway to requests.  (This is the UserSpaceSession Actor in my world: for a given "Space" -- a database, essentially -- there is one Session Actor for each User currently working with it.)  That makes a very nice mediating point for the API.


As for hand-constructing the AJAX: Play actually provides some tools to make that easier.  See this code section that I have in my Play template page that wraps around the ScalaJS Client.  This basically uses Play's machinery to introspect on the specified controllers, and auto-generates Javascript AJAX wrappers for each entry point in those controllers.  So I never hand-construct AJAX calls.

In the client ScalaJS code, I use these classes to wrap those AJAX wrappers in a more Scala-ish idiom, so I can say things like

controllers.Application.apiRequest(userName, spaceId).callAjax("pickledRequest" -> request)

Finally, at the top level, I have an Autowire Client object that wraps everything up in Autowire style, and that's what the actual application code uses.  (Note that this actually uses several different Play entry points on the server: those are for fundamentally different kinds of calls, and go to different Actors in different Troupes in the back end.)


Basically, my recommendation is to think about what your client/server architecture would ideally look like, if Play wasn't even involved.  What is the real API, what Actors should it get routed to, and would it be easier to have another Actor do the API routing instead of Play?  In my case, that turned out to be mostly yes, and Play is gradually getting relegated to mainly plumbing for the Autowire request.  (Eventually, I expect it to entirely go away, in favor of a bunch of sbt-web modules mixed into akka-http.)  But like I said, YMMV...

--
You received this message because you are subscribed to the Google Groups "Scala.js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-js+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/scala-js/8fcc7398-02ce-40e5-947f-e4f127e8e171%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Sébastien Doeraene

unread,
Jan 12, 2015, 9:34:55 AM1/12/15
to SemanticBeeng ., scal...@googlegroups.com
Hi,

I'll reply inline to some of your questions:

1. "The Jasmine test framework is not a good testing framework for Scala.js code, and is being removed in 0.6.x."


Q: Where can I learn more about this and understand why Jasmine is bad for ScalaJS testing?
JavaScript has impressive support for testing async code with promises: chai as promised, sinon.js, jasmine, mocha, etc 

What does "bad" mean in terms of one being able to use this existing support?

The main problem is that Jasmine does not understand Scala. It does not understand what == means in Scala (i.e., the equals() method). It does not understand Scala's Futures. It does not understand that exceptions are typed, and that a certain type of exception can be expected. That kind of things.

In practice, writing Jasmine tests in Scala.js turns more into: how can I convince Jasmine to compare my things the way I want to? Rather than focusing on my tests.
 
2. utest seems to support async tests 


Q: Does utest mean to provide full support for promises?

Would one be able to use native JavaScript promise support to test JSExported shared APIs?
From utests? 
From other kinds of tests?

Or does "bad" in the above definition means that this is not a good idea?

By Promises, do you mean Scala's Promises (one of the ways to construct Futures) or do you mean JavaScript's Promises/A+ style?
uTest supports Scala's Futures, and hence Promises.
I don't think it ever intends to support directly the JavaScript style of Promises/A+. But one could write static types for Promise/A+ and implicit conversions to/from Scala's Futures, giving near-transparent interop.

3. ScalaJS has support for scala Futures (scala.concurrent.Future)

References 

Q: Does utest mean to support testing such APs?

It does, as per the first link you mentioned in 2.
That said, you probably also need your Web server to be running while you execute your tests. I don't really know how to do that. It's a more an integration test à la Selenium, I suppose?

4. Autowire also uses Futures.

Q: Does utest support testing such APIs? Any examples handy?

Same answer.

Finally

Q: Can you please suggest some material to better understand how to BDD this ScalaJS based command layer that specifies the semantics of the shared business API given that it needs to be specified with "promises" (see [1])?

Hum ... No idea. That's for the guys actually using Scala.js for real stuff to answer. I'm only the compiler guy ^^

Cheers,
Sébastien

Benjamin Jackman

unread,
Jan 12, 2015, 9:53:22 AM1/12/15
to scal...@googlegroups.com, semanticbeen...@gmail.com
Just wondering: What are some of the limitations in terms of classes you can represent that you have encountered?

SemanticBeeng .

unread,
Jan 12, 2015, 10:29:04 AM1/12/15
to Sébastien Doeraene, scal...@googlegroups.com
Thank you.

I meant " JavaScript's Promises/A+ style".

"But one could write static types for Promise/A+ and implicit conversions to/from Scala's Futures, giving near-transparent interop"
Okay. so then I could use this to "escape" from ScalaJS generated JavaScript with native JavaScript Jasmine tests...

Not being stubborn but not sure I understand "The main problem is that Jasmine does not understand Scala".
If you are trying to put a Scala API over Jasmine to write ScalaJS tests with it then I can imagine.

But if I used "native" Jasmine to test the JSExported "business interface" then Jasmine would not be in conflict or "bad", would it?

Surely I can see how doing this one would lose a lot of the benefit of using ScalaJS because tests would not be typesafe.

I will do more diligence into the utest support for promises and if it provides enough so I would not need "chai as promised" and the rest. 
Curious if you guys see value in "chai as promised" or "sinon.js" for utests.



Justin du coeur

unread,
Jan 12, 2015, 10:36:35 AM1/12/15
to Benjamin Jackman, scal...@googlegroups.com, SemanticBeeng .
On Mon, Jan 12, 2015 at 9:53 AM, Benjamin Jackman <benjamin...@gmail.com> wrote:
Just wondering: What are some of the limitations in terms of classes you can represent that you have encountered?

Not much that have proven to be issues for me, but you can't just stuff arbitrary classes into it.  I should note, the limitations are actually uPickle rather than Autowire.  (Autowire does *not* require uPickle, but they work well together.)  Basically, the trait hierarchy you're putting through uPickle has to be reasonably self-contained for the macros to work -- you can't just feed any arbitrary extensible class to it.  case classes and sealed hierarchies work great, and IMO that's usually the right way for APIs to think.

IIRC, the only issue I encountered was something involving two closely-related traits that crossed package boundaries in some fashion.  We discussed that in the uPickle repo, but I don't recall whether it got resolved.  Otherwise, it's worked smoothly, and the limitations are pretty clearly described on the uPickle GitHub page...

Sébastien Doeraene

unread,
Jan 12, 2015, 10:37:29 AM1/12/15
to SemanticBeeng ., scal...@googlegroups.com
Oh right, if you want to test the JS API that comes out of @JSExported Scala.js code, then by all means use any JavaScript framework you like. In that case it'll be in its JavaScript form.

The Jasmine test framework we refer to in the announcement was a Scala interface to the Jasmine test framework. That one should not be used anymore.

Cheers,
Sébastien

Ben Hutchison

unread,
Jan 12, 2015, 5:20:25 PM1/12/15
to Justin du coeur, Benjamin Jackman, scal...@googlegroups.com, SemanticBeeng .
On Tue, Jan 13, 2015 at 2:36 AM, Justin du coeur <jduc...@gmail.com> wrote:
On Mon, Jan 12, 2015 at 9:53 AM, Benjamin Jackman <benjamin...@gmail.com> wrote:
Just wondering: What are some of the limitations in terms of classes you can represent that you have encountered?

Not much that have proven to be issues for me, but you can't just stuff arbitrary classes into it.  I should note, the limitations are actually uPickle rather than Autowire.  (Autowire does *not* require uPickle, but they work well together.) 

As Justin said, the limitations are in uPickle, which is Autowire's "default" serializer. These include 2 that cause problems for me:

- Shared objects in the serialized graph unsupported
- Non-sealed class hierarchies unsupported 

That's partly why I wrote & use Prickle [https://github.com/benhutchison/prickle], which AFAIK is the most full-featured Scala.js serialization library ATM, and integrates easily with autowire [example https://github.com/benhutchison/mg-client/blob/master/src/main/scala/mg/MemoryGame.scala#L20].

-Ben

Haoyi Li

unread,
Jan 12, 2015, 5:28:32 PM1/12/15
to Ben Hutchison, Justin du coeur, Benjamin Jackman, scal...@googlegroups.com, SemanticBeeng .
Looks like the effort I put into making autowire stand-alone has paid off ^_^ 

--
You received this message because you are subscribed to the Google Groups "Scala.js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-js+u...@googlegroups.com.

Benjamin Jackman

unread,
Jan 12, 2015, 5:31:37 PM1/12/15
to Haoyi Li, Ben Hutchison, Justin du coeur, scal...@googlegroups.com, SemanticBeeng .

On Mon, Jan 12, 2015 at 4:28 PM, Haoyi Li <haoy...@gmail.com> wrote:
Looks like the effort I put into making autowire stand-alone has paid off ^_^ 

​Well it has for us as well, as we use cgta/serland​ :)​

Ben Hutchison

unread,
Jan 12, 2015, 5:46:43 PM1/12/15
to Sébastien Doeraene, SemanticBeeng ., scal...@googlegroups.com
On Tue, Jan 13, 2015 at 1:34 AM, Sébastien Doeraene <sjrdo...@gmail.com> wrote:
1. "The Jasmine test framework is not a good testing framework for Scala.js code, and is being removed in 0.6.x."


Q: Where can I learn more about this and understand why Jasmine is bad for ScalaJS testing?
JavaScript has impressive support for testing async code with promises: chai as promised, sinon.js, jasmine, mocha, etc 

What does "bad" mean in terms of one being able to use this existing support?

The main problem is that Jasmine does not understand Scala. It does not understand what == means in Scala (i.e., the equals() method). It does not understand Scala's Futures. It does not understand that exceptions are typed, and that a certain type of exception can be expected. That kind of things.

In practice, writing Jasmine tests in Scala.js turns more into: how can I convince Jasmine to compare my things the way I want to? Rather than focusing on my tests.


Interesting, thanks for the explanation. 

So this increases the importance of community test tools in supporting the scala.js ecosystem. You mentioned 4 tools in the announcement:

My question to the list is, which do you use and why? What are the pros/cons?

Ive used uTest so far, haven't yet bothered to look wider. On the plus side, it gets the job done, and its cross-JS/JVM. On the downside, its results output needs improvement, and Im skeptical if the whole assertions-with-local-variable-capture is in fact the best approach [https://github.com/lihaoyi/utest/issues/41].

-Ben
 

Sébastien Doeraene

unread,
Jan 12, 2015, 6:09:17 PM1/12/15
to Ben Hutchison, SemanticBeeng ., scal...@googlegroups.com
Hi,

In my case, I use none of them, because I don't write actual Scala.js code ^^ Others than me should answer that question.

Cheers,
Sébastien

Justin du coeur

unread,
Jan 12, 2015, 6:12:25 PM1/12/15
to Ben Hutchison, Sébastien Doeraene, SemanticBeeng ., scal...@googlegroups.com
On Mon, Jan 12, 2015 at 5:46 PM, Ben Hutchison <brhut...@gmail.com> wrote:
My question to the list is, which do you use and why? What are the pros/cons?

Ive used uTest so far, haven't yet bothered to look wider. On the plus side, it gets the job done, and its cross-JS/JVM.

Ditto, largely the same reason, although I don't actually care about the JVM side.  (I have lots of ScalaTest code on the server side, so I'm unlikely to switch there.) 

Baldur Norddahl

unread,
Jan 13, 2015, 2:09:45 AM1/13/15
to scal...@googlegroups.com

I am seeing lots of people trying to work around Play in this thread. I too have a Play application with Scala-js. But now I am strongly considering ditching Play altogether and switch to an Akka based application. I am not using much of what Play provides as the UI is now handled by Scala-js and Scalatags, routing by autowire etc. So seems like all you need is Akka+spray on the server side.

Regards

Baldur

Haoyi Li

unread,
Jan 13, 2015, 2:23:43 AM1/13/15
to Baldur Norddahl, scal...@googlegroups.com
I am seeing lots of people trying to work around Play in this thread. I too have a Play application with Scala-js. But now I am strongly considering ditching Play altogether and switch to an Akka based application. I am not using much of what Play provides as the UI is now handled by Scala-js and Scalatags, routing by autowire etc. So seems like all you need is Akka+spray on the server side.

Yeah, that's why I've put all effort into Scala.js and fiddling with Spray instead of Play. Play might be optimal for what it does, but it's optimizing for a layer that no longer needs to exist. 

--
You received this message because you are subscribed to the Google Groups "Scala.js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-js+u...@googlegroups.com.

Justin du coeur

unread,
Jan 13, 2015, 7:49:56 AM1/13/15
to Haoyi Li, Baldur Norddahl, scal...@googlegroups.com
On Tue, Jan 13, 2015 at 2:23 AM, Haoyi Li <haoy...@gmail.com> wrote:
Yeah, that's why I've put all effort into Scala.js and fiddling with Spray instead of Play. Play might be optimal for what it does, but it's optimizing for a layer that no longer needs to exist.

Largely agreed.  The really important thing is that Play! is no longer a monolithic entity: it's mostly been broken up into components that you can pick and choose among, so there's no longer a reason to use the whole big thing.

Personally, I'm waiting for the transition from Spray to akka-io to settle down, and for the akka-http stack to get a bit more mature.  But I figure that I'll probably switch away from Play per se sometime in the next year...

SemanticBeeng

unread,
Jan 13, 2015, 12:23:56 PM1/13/15
to scal...@googlegroups.com, baldur....@gmail.com

If one looks for "RPC" (remote calling)  then Play! web controllers and Spray or Akka-http are similar. Is that the point of this sub-thread?

Next, the actor model can be used for implementing "user session" based scenarios.

(But) Did anyone use the actor model with the DDD Sagas or long lived business transactions/processes?
"Improving Akka Persistence wrt CQRS/ES/DDD" is a discussion on this but have not found much more.

Justin du coeur

unread,
Jan 13, 2015, 12:32:11 PM1/13/15
to SemanticBeeng, scal...@googlegroups.com, Baldur Norddahl
On Tue, Jan 13, 2015 at 12:23 PM, SemanticBeeng <semanticbeen...@gmail.com> wrote:
(But) Did anyone use the actor model with the DDD Sagas or long lived business transactions/processes?
"Improving Akka Persistence wrt CQRS/ES/DDD" is a discussion on this but have not found much more.

I recommend asking on the akka-user Google Group; there seem to be a lot of relatively serious CQRS/DDD folks there.  This group tends to be a bit more UI focused (certainly more client-focused), by the nature of the tech...

SemanticBeeng .

unread,
Jan 13, 2015, 1:01:46 PM1/13/15
to Justin du coeur, scal...@googlegroups.com, Baldur Norddahl
"This group tends to be a bit more UI focused (certainly more client-focused), by the nature of the tech..."

I know that Justin. It was not my intent to "perpetrate" an Akka discussion here. :-) 

In only came up in the context of questions about use of Scala.JS with Play! and A+ promises support in uTest.

SemanticBeeng .

unread,
Jan 15, 2015, 3:03:21 PM1/15/15
to Sébastien Doeraene, haoy...@gmail.com, scal...@googlegroups.com
Hi guys

More to explain what I meant by this thread.

I would like to be able to write my tests like this http://www.robotlovesyou.com/bdd-tdd/: using these cool JavaScript native libraries chai as promised, sinon, etc.
And ideally not have to bring over to Scala.JS all these native libs...
Basically I would like to write my 

1. shared business interface and
2. functional domain models (https://github.com/SemanticBeeng/immutable-domain-example, cloned) 
3. the CQRS:command layer 

with Scala.JS (this I can do) ..

But the rest of the client code I would like to write in in (here comes) TypeScript.
This is not because I like TypeScript but because 

1. well, may not be able to write all code in Scala.JS (could I?, plus we lose JavaScript developers)
2. TS it is a few notches better than JS in terms of typesafety.
3. definitelytyped.org has tons of d.ts-es for most major JavaScript libraries.

So I could write such tests in this combination of languages.

uTest is awesome for Scala.JS but really would be gorgeous-er to not be constrained to not use stuff implemented in JavaScript.

Q: Is this making sense? Do you see the value?

Q: Is there some way to achieve this with the existing tools and am missing it?

Possible solution 1.
Could definitelytyped.org stuff be auto imported in Scala.JS
I know about https://github.com/sjrd/scala-js-ts-importer but given it is not really automatic it would perhaps make sense to start something like scalajs.definitelytyped.og where we would maintain the conversions done with manual TLC.
Or maybe this is better (by Sebastien): https://github.com/apezel/ts2scala

Possible solution 2.
Is there a way to write the Scala.JS compiler to ... embed Scala.JS into TypeScript?

Given Scala's powerful DSL capabilities maybe it is doable to create a cross TypeScript/Scala compiler.

 
Again, the "business" need would be to use Scala.JS core code combined with TypeScript code for logic of web layer to drive BDD specs (http://www.robotlovesyou.com/bdd-tdd/) and actual application implementation.

Thoughts on validity on the need and possible solutions, please.

Cheers & thanks
Nick

Sébastien Doeraene

unread,
Jan 15, 2015, 4:46:51 PM1/15/15
to SemanticBeeng ., scal...@googlegroups.com
Hi,


well, may not be able to write all code in Scala.JS

Why not? Scala.js can do everything. OK, using JS testing framework is awkward, to the point where it's ridiculously more annoying than using a Scala.js testing framework. But as far as libraries are concerned, Scala.js does not impose limitations on the things you can do with your code.

plus we lose JavaScript developers

OK, fair enough.


Q: Is this making sense? Do you see the value?

If all your logic is in Scala.js, I don't see the point on insisting upon a JS testing framework. If you have a significant logic base in JS, then yes, I see the value, but then, next question:


Q: Is there some way to achieve this with the existing tools and am missing it?

Yes, you can just rewire the `test` task in sbt to execute a JS testing framework. It won't integrate as well as a Scala.js testing framework (e.g., no testOnly nor testQuick), but should otherwise be pretty straightforward.


Possible solution 1.
Could definitelytyped.org stuff be auto imported in Scala.JS
I know about https://github.com/sjrd/scala-js-ts-importer but given it is not really automatic it would perhaps make sense to start something like scalajs.definitelytyped.og where we would maintain the conversions done with manual TLC.
Or maybe this is better (by Sebastien): https://github.com/apezel/ts2scala

No, that's not possible. There are things you can express more precisely in the Scala type system than in the TS type system, so there is always a part of human interaction to produce the best possible typings in Scala.js. Conversely, there are (a few) things that TS can do and Scala can't (yet), but these can be collapsed (which is what the TS importer does).

The macro-based approach must necessarily have the same limitations. There is simply no way around it.

In addition, as I mentioned a few times already, static typing libraries should be published in artifacts just like any other Scala.js library. There is *no reason whatsoever* to want to keep all their sources in a single place. This is going back 20 years in terms of dependency management, compared to libraryDependencies in sbt.


Possible solution 2.
Is there a way to write the Scala.JS compiler to ... embed Scala.JS into TypeScript?
Given Scala's powerful DSL capabilities maybe it is doable to create a cross TypeScript/Scala compiler.

Er ... no, that doesn't sound possible. What would it even look like?


Again, the "business" need would be to use Scala.JS core code combined with TypeScript code for logic of web layer to drive BDD specs (http://www.robotlovesyou.com/bdd-tdd/) and actual application implementation.

Sure, if this is what you want to do, that's perfectly possible. Just make sure to @JSExport all the stuff you want to call from your TypeScript code, and go ahead. You won't get the types for free in TS, though. You'll have to use 'any' or write the .d.ts files yourself. I suppose one could write a compiler plugin for Scala.js that would generate .d.ts files for @JSExported stuff. (Yeah, that's actually a fun thing to do ^^)

BTW: about this "embedding", what does 'Implicits to make "writing JavaScript" easier' here http://www.scala-js.org/news/2014/12/22/announcing-scalajs-0.6.0-M3/ means?
Any examples please?

This is mostly for the (hopefully) rare cases when you want to write in a JavaScript style (dynamic typing, truth values, etc.) embedded within Scala.js. We don't have many examples, because, as I said, it's pretty rare. Here are a couple:
https://github.com/scala-js/scala-js/blob/v0.6.0-RC1/javalanglib/src/main/scala/java/lang/System.scala#L17-L32
https://github.com/scala-js/scala-js/blob/v0.6.0-RC1/javalanglib/src/main/scala/java/lang/System.scala#L258-L268
https://github.com/scala-js/scala-js/blob/v0.6.0-RC1/library/src/main/scala/scala/scalajs/runtime/Bits.scala#L19-L21
and the big one:
https://github.com/scala-js/scala-js/blob/v0.6.0-RC1/library/src/main/scala/scala/scalajs/runtime/StackTrace.scala#L274-L338

So if I want to use the JSExported code to write BDD/async/promise code like this
then should all be smooth or should I expect the kind of (interoperability) pain you had when trying to make Jasmine work with such JSExported code?

All should be smooth.

Cheers,
Sébastien

On Thu, Jan 15, 2015 at 9:44 PM, SemanticBeeng . <semanticbeen...@gmail.com> wrote:
So if I want to use the JSExported code to write BDD/async/promise code like this


then should all be smooth or should I expect the kind of (interoperability) pain you had when trying to make Jasmine work with such JSExported code?

Asking because if this is smooth, then doing this compared to uTest based tests means 

1. in uTest I have the typesafety 
2. this way I have the entire world of JavaScript libraries (including the respective async/promise stuff).

Asking because my gut tells me I am missing something about uTest ... 

(this is in the context of my previous post today)
Just like I said there it seems a pity to lose JavaScript developers in writing BDD specs if I can only use ScalaJS.
I have a team of guys who do not want to learn Scala but are very good in JavaScript, nor do I want to write JavaScript (but I want to write this shared logic in Scala.JS).

If this angle was debated before please reference me there but fresh insights are always better. :-)

Thank you



On Mon, Jan 12, 2015 at 10:37 AM, Sébastien Doeraene <sjrdo...@gmail.com> wrote:

Sébastien Doeraene

unread,
Jan 16, 2015, 11:51:18 AM1/16/15
to SemanticBeeng ., scal...@googlegroups.com
What does "surrounding TypeScript" mean? Do you want files that contain both TS and Scala code? That would screw up any IDE alive. And I would find that *very* confusing.
You can very well have some TS files, some Scala.js files, and compile them separately. As I mentioned, yes, someone could create a plugin that would emit .d.ts files from @JSExports. And these .d.ts files could be fed to the TS compiler when compiling its TS files. But a hybrid compiler? No, thanks. (No one ever wanted hybrid Java/Scala files, did they? This is the same.)

Cheers,
Sébastien

On Fri, Jan 16, 2015 at 5:35 PM, SemanticBeeng . <semanticbeen...@gmail.com> wrote:
Thanks for the detailed reply, Still mulling,

"Er ... no, that doesn't sound possible. What would it even look like?"

Thinking of an simple "embedding" at the level of the JSExported api 

1. the exported api is, by definition, JavaScript which is valid TypeScript (?).
2. having these referenced from surrounding TypeScript would all be seamless if a tool would generate TypeScript from the JSExporrts.

Then we would get some of the typesafety (of the mix) back because of TypeScript.

Thinking this out loud...
Would this not extend Scala.JS adoption in a material way?
 
Nick

SemanticBeeng .

unread,
Jan 16, 2015, 12:07:49 PM1/16/15
to Sébastien Doeraene, scal...@googlegroups.com
No, no hybrid compiler of course, evidently no point in that. Two differently worlds doing very well on their own.

The JSExports provide the interop boundary.

"a plugin that would emit .d.ts files from @JSExports": that is what I meant.

What would it take?
Would some of your previous TypeScript work be reusable?

Sébastien Doeraene

unread,
Jan 16, 2015, 12:09:41 PM1/16/15
to SemanticBeeng ., scal...@googlegroups.com
The TS importer goes the other way around, so it's not helpful.

It would take a couple hundreds of lines of code in a scalac plugin, I suppose. Not an insurmountable task if you're willing to dive in the scalac plugin adventure.

Sébastien

Sébastien Doeraene

unread,
Jan 16, 2015, 12:46:18 PM1/16/15
to SemanticBeeng ., scal...@googlegroups.com
For calling JS/TS code from Scala.js? That's standard interop with JavaScript from Scala.js (with facade types and such). Exactly the same way you call the DOM API. So examples would be the calls to the DOM API here:
http://scala-js.github.io/scala-js-dom/

Sébastien

On Fri, Jan 16, 2015 at 6:40 PM, SemanticBeeng . <semanticbeen...@gmail.com> wrote:
Okay.

And how to connect the Scala.JS objects with the TypeScript generated JS at runtime?
To wrap the actual implementation with the API?

Maybe I can live with handcrafted TS for now.

I remember some magic from Scala.JS to bind to external JS.
Maybe you will be kind to reference some examples,

Thank you much

SemanticBeeng .

unread,
Jan 16, 2015, 1:10:14 PM1/16/15
to Sébastien Doeraene, scal...@googlegroups.com
Here's an example of what I mean by binding Scala.JS code with the JS from the generated TypeScrript API


this is an example var phoneNumber = $.extend(new PhoneNumber(), yourJSONObject);


Somehow the prototype of the generated TypeScript must redirect calls to the actual implementation exported ..

Is this making sense?



On Fri, Jan 16, 2015 at 12:49 PM, SemanticBeeng . <semanticbeen...@gmail.com> wrote:
Thanks, no I meant the other way, from JS but then realized that is JavaScript specific thing.
Maybe by connecting the prototypes... but the JsExported generated JavaScript is not as simple as a class with a prototype...

Sébastien Doeraene

unread,
Jan 16, 2015, 1:13:32 PM1/16/15
to SemanticBeeng ., scal...@googlegroups.com
That's only a matter of exporting. With this:

@JSExport("PhoneNumber")
@JSExportAll
case class PhoneNumber(...)

Your JS code 'new PhoneNumber(...)' will just work. That's the whole point of @JSExport.

Sébastien

SemanticBeeng .

unread,
Jan 16, 2015, 1:37:51 PM1/16/15
to Sébastien Doeraene, scal...@googlegroups.com
But would not be typesafe in a TypeScript sense, would it.

If the Scala.js api changes I will not know until runtime.

The idea of this scalac plugin would be to address this by generating the TypeScript equivalent for the JSExport but then still I need to connect/bind the two: the strongly typed interface and the Scala.js generated implementation.

The question was how to bind the two,

Sébastien Doeraene

unread,
Jan 16, 2015, 1:43:09 PM1/16/15
to SemanticBeeng ., scal...@googlegroups.com
If you have a plugin it will generate exactly the static types for the exported stuff, so it will already be "connected" in that sense. By construction.

Sébastien

SemanticBeeng .

unread,
Jan 16, 2015, 1:48:39 PM1/16/15
to Sébastien Doeraene, scal...@googlegroups.com
Okay, I see you meant to generate a full binding and not just the interface.
Makes sense.

As an intermediate solution: I if manually crafted the TypeScript interface, is the binding a mechanical thing also doable by hand or is not feasible due to the complexities of the generated code?

Thanks for taking it this far.

Sébastien Doeraene

unread,
Jan 16, 2015, 1:52:07 PM1/16/15
to SemanticBeeng ., scal...@googlegroups.com
The binding is *automatic*, whatever you do. @JSExport puts stuff in the global scope. TS types assume things are in the global scope. Both agree, end of story. I don't understand what else you're trying to "bind".

Sébastien

SemanticBeeng .

unread,
Jan 16, 2015, 3:05:19 PM1/16/15
to Sébastien Doeraene, scal...@googlegroups.com
All right will see how this goes.

Thanks

On Fri, Jan 16, 2015 at 2:31 PM, Sébastien Doeraene <sjrdo...@gmail.com> wrote:
Yes, that's right.

Sébastien

On Fri, Jan 16, 2015 at 8:26 PM, SemanticBeeng <semanticbeen...@gmail.com> wrote:
You say "agree" (at compile time) because at runtime we would not use the TypeScript generated code but (only) the Scala.JS generated with the same runtime API.

I was saying "bind" thinking the TypeScript generated code would also be involved at runtime and the two would need to work together.
But the TypeScript generated would be simply discarded at runtime....

So then the handcrafted TypeScript approach would work.
Maybe then I can start all this shared business interface from TypeScript and generate the Scala.JS interfaces as a matter of development procedure to keep cross language typesafety.

I have to actually try this because the theory only goes so far.

Please confirm or advise.

Thank you much
Nick

SemanticBeeng

unread,
Jan 18, 2015, 12:22:28 PM1/18/15
to scal...@googlegroups.com, semanticbeen...@gmail.com, sjrdo...@gmail.com, scal...@googlegroups.com
Actually I found this actors related implementation by Sébastien.in ScalaJS: https://github.com/sjrd/scala-js-actors

Sébastien, was this meant to also provide the equivalent of "projections" or "views" in this Akka definition http://devblog.consileon.pl/2014/06/17/reactive-ddd-with-akka-lesson-3-projections/?
In your latest code I found no reference to such thing.


<Context of question>
I am implementing a functional domain model which also lives on the ScalaJS client and am trying to determine the best way to keep the client version in sync.

Or, I could pursue an Akka PersistentView approach http://doc.akka.io/api/akka/2.3.5/index.html#akka.persistence.PersistentView 

Side comment: I find CQRS a bit at odds with the rich client application paradigm because there is rarely an actual "query" from the client.
<end context>

Please advise.
If your answer is 'no' then will know not to ask about Akka on this group.

Thanks in advance
Nick

Sébastien Doeraene

unread,
Jan 18, 2015, 1:08:50 PM1/18/15
to SemanticBeeng, scal...@googlegroups.com
Hi,

The Actors implementation in my repo was a very rough proof of concept, and only supporting the content of the akka-actor.jar, i.e., actors and schedulers. I don't plan to work on this anymore myself.

Sébastien

SemanticBeeng .

unread,
Jan 19, 2015, 11:30:55 AM1/19/15
to Justin du coeur, scal...@googlegroups.com
Reviewed more of this Justin. It will help me, thank you.


"
@TODO: this isn't bad, but it's still mediocre -- since it's js.Dynamic, there's no static checking
* of the calls at all. We'd like to do something that's truly strongly typed, but Autowire isn't the
* solution to this particular problem, since it's fundamentally Play-based. The right solution is
* probably at compile time, to build something that gets at the routing information *before* Scala.js,
* reflects on that, and generates the client-side glue code.
"
What would you say of this approach of starting with a TypeScript equivalent of the JSExported shared ScalaJS apis?

see whole thread here. 
It is kinda long because I was thinking out loud ..


Let me know if 
1. your motivation varies than mine (see references to writing BDD tests in TypeScript)
2. you can imagine any reason why starting to a TypeScript for the shared APIs would not work and/or provide the strong typesafety you were looking for.

I plan to experiment with the TypeScript importers like ts2scala.

Nick


On Mon, Jan 12, 2015 at 9:20 AM, Justin du coeur <jduc...@gmail.com> wrote:
So the question I eventually realized I should be focusing on was that my *real* entry point was very different from where the Play! architecture had led me to.  That is, I had my big Akka back end, with Play sitting on top of it -- requests would come into Play via AJAX, Play would unmarshall them and feed them into the correct Akka actors, those Actors would return the answer and Play would remarshall it.  From that POV, Autowire didn't add much.

But what I gradually realized was that the *real* API was the Actor, not Play.  So I would up instead adding one new entry point to Play (kind of -- see below), which deserialized the request but did *not* route it.  Instead, that entry point is designed to take just enough information to find the right Actor, and it passes the deserialized Autowire Request to that Actor.  The *Actor* then creates a one-off object to handle the request, and routes into that object.

This took a while to set up and get right (gradually evolved over a couple of weeks), but now that I've got it, it's a thing of beauty -- when I want to add a new entry point, or edit an existing one, I just edit the API trait and the implementing object, and It Just Works.  Even adding whole new APIs is proving fairly easy: I just add another implementing class and another routing pathway, which takes maybe two minutes.

Even more significantly: when I moved away from doing the plumbing through Play, and stopped having to do lots of fiddly serialization of my business objects, the amount of code dropped *dramatically*.  The new versions of my API implementations, using Autowire, are running about a third the size of my old Play ones, simply because the connection is tighter and more natural.  Since it's all just Scala at all levels, without having to think about JSON at all (except as an under-the-hood implementation detail), it's much easier.

YMMV -- this approach is very well-suited to my architecture, where the user is primarily talking to a single interface Actor that serves as the gateway to requests.  (This is the UserSpaceSession Actor in my world: for a given "Space" -- a database, essentially -- there is one Session Actor for each User currently working with it.)  That makes a very nice mediating point for the API.


As for hand-constructing the AJAX: Play actually provides some tools to make that easier.  See this code section that I have in my Play template page that wraps around the ScalaJS Client.  This basically uses Play's machinery to introspect on the specified controllers, and auto-generates Javascript AJAX wrappers for each entry point in those controllers.  So I never hand-construct AJAX calls.

In the client ScalaJS code, I use these classes to wrap those AJAX wrappers in a more Scala-ish idiom, so I can say things like

controllers.Application.apiRequest(userName, spaceId).callAjax("pickledRequest" -> request)

Finally, at the top level, I have an Autowire Client object that wraps everything up in Autowire style, and that's what the actual application code uses.  (Note that this actually uses several different Play entry points on the server: those are for fundamentally different kinds of calls, and go to different Actors in different Troupes in the back end.)


Basically, my recommendation is to think about what your client/server architecture would ideally look like, if Play wasn't even involved.  What is the real API, what Actors should it get routed to, and would it be easier to have another Actor do the API routing instead of Play?  In my case, that turned out to be mostly yes, and Play is gradually getting relegated to mainly plumbing for the Autowire request.  (Eventually, I expect it to entirely go away, in favor of a bunch of sbt-web modules mixed into akka-http.)  But like I said, YMMV...

On Mon, Jan 12, 2015 at 8:49 AM, SemanticBeeng <semanticbeen...@gmail.com> wrote:
Thanks, Justin.

Will think this over then,

Here's how I look at AutoWire

1. On the client I still have to worry about handcrafting the Ajax call: urls, get, post, etc
With PLay! generated routers this is done for me

  override def doCall(req: Request): Future[String] = {

    print(req.path)
      url = "/api/" + req.path.mkString("/"),
      data = upickle.write(req.args)
    ).map(_.responseText)
  }

2. On the server 

        post {
          path("api" / Segments) { s =>
            extract(_.request.entity.asString) { e =>
              complete {
                AutowireServer.route[CustomerMgmtService](Server)(
                  autowire.Core.Request(s, upickle.read[Map[String, String]](e))
                )
              }
            }
          }
        }

is handled by Play! 

But of course you know this.

Maybe you can share some examples for my education?

Are you saying that you are not calling Play! controllers much but communicate over Akka between your Scala and ScalaJS parts of the app?
So are you using ScalaJS actors then?

If I do not use Akka but controllers then would you still say it makes more sense to use AutoWire?

With what I had in mind I'd do nothing more than just (somehow) add the strongly typed interface to the JavaScript routes generated by Play!
I assume there is a way to do this nicely with ScalaJS's ability to use native JavaScript but have not tried this yet.

So I would not need Autowire at all but achieve the same typesafety AutoWire brings.
I like AutoWire but do not see why I would use it with Play!. I only need the typesafety AutoWire promotes.

Please share more insights.

Thanks
Nick


On Monday, January 12, 2015 at 7:54:41 AM UTC-5, Justin du coeur wrote:
I'll let Haoyi tackle most of this, since he knows it better, but one comment from experience:

On Sun, Jan 11, 2015 at 11:33 PM, SemanticBeeng . <semanticbeen...@gmail.com> wrote:
To implement this layer I am considering using Autowire but Play! makes much of it unnecessary. 
Thinking to reuse the shared API to wrap the JavaScript routes generated by Play! instead. 
This is supposed to provide even better typesafety than AutoWire because the Ajax calls itself will no longer be handcrafted like with AutoWire.

This is the approach I started with -- mainly focused on my existing Play infrastructure, and adding a bit of Autowire on top of it -- but I've wound up switching to exactly the other way.  After working with it for a while, I've found that maintaining Autowire APIs is significantly easier than doing so with Play, and I spent less effort mucking with the translations.  Moreover, my Autowire API is wired much more *deeply* into my server: I spent a while writing the plumbing in Play, but now just ignore it and focus on connecting my ScalaJS front end directly to my Akka actors in the back end via Autowire.

Autowire isn't a panacea -- it does have some specific limitations in terms of the classes you can represent and such.  But I've found that those limitations are generally fine when I'm thinking in API terms, and it mostly just works now that the plumbing is done... 

--
You received this message because you are subscribed to the Google Groups "Scala.js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-js+u...@googlegroups.com.

Justin du coeur

unread,
Jan 20, 2015, 10:25:32 AM1/20/15
to SemanticBeeng ., scal...@googlegroups.com
On Mon, Jan 19, 2015 at 11:30 AM, SemanticBeeng . <semanticbeen...@gmail.com> wrote:
Reviewed more of this Justin. It will help me, thank you.


"
@TODO: this isn't bad, but it's still mediocre -- since it's js.Dynamic, there's no static checking
* of the calls at all. We'd like to do something that's truly strongly typed, but Autowire isn't the
* solution to this particular problem, since it's fundamentally Play-based. The right solution is
* probably at compile time, to build something that gets at the routing information *before* Scala.js,
* reflects on that, and generates the client-side glue code.
"

Note that that comment is quite old (relative to this codebase), and predates me getting deeply into Autowire.  It has become essentially irrelevant, though: while this facade *is* weakly-typed, it's turned out to be a one-off that never changes, so it doesn't matter much.

Basically, at the time I was writing this, I still thought I was going to be coding to Play APIs.  That proved to simply not be as good as building proper Autowire APIs instead.  That is, ScalaJS + Play APIs is better than JavaScript + Play APIs -- but it's still not nearly as good as end-to-end Autowire.  And that's with the current state of Autowire, which is still evolving and improving.

I have wound up targeting fewer and fewer Play entry points with this; that may eventually get all the way down to one Play API with only three entry points.  So I'm less concerned about the fact that the entry points are not themselves type-checked at compile time.

What would you say of this approach of starting with a TypeScript equivalent of the JSExported shared ScalaJS apis?

I'll be honest: I think that adding TypeScript to the mix is *not* a good idea.  It makes your environment more complicated, with *three* languages involved on the client side, so development is likely to become a hash of confusion.

YMMV, but I have usually found that in the long run, simplifying the development environment is better than complicating it.  That's part of why I've bet my company on the Scala stack, and committed completely to ScalaJS -- it allows me to write my entire end-to-end stack in a single language.  Yes, I'll have to teach Scala to some programmers, but then they'll be able to work at all levels of the stack...

SemanticBeeng .

unread,
Feb 2, 2015, 11:34:02 PM2/2/15
to Haoyi Li, scal...@googlegroups.com
Hi,

Can anyone please advise if this is supposed to run in uTest?


this is the test 

Specifically this one

"A plan can have two tasks" - {
assert($.taskPlan.isEmpty)
$.do_scheduleNew("Do this") andThen { case r =>
val taskId = r.get.value
$.do_complete(taskId)
} andThen { case _ =>
$.do_clearCompletedTasks
}
}

The do_* method return futures. 
Aiming to get as much common ground with Specs2.


This shared code runs well under Spec2 but cause this under uTest.

[jvm] $ +js/test
[info] Setting version to 2.11.2
[info] Set current project to jvm (in build file:/home/nickdsc/projects/playframework-learn/play-scalajs-showcase/)
[info] Compiling 4 Scala sources to /home/nickdsc/projects/playframework-learn/play-scalajs-showcase/js/target/scala-2.11/test-classes...
Cleared 1 tasks
[trace] Stack trace suppressed: run last js/test:loadedTestFrameworks for the full output.
[trace] Stack trace suppressed: run last js/test:test for the full output.
[error] Could not run test domain.TaskManagementSpecuTest: org.scalajs.jsenv.ComJSEnv$ComClosedException: JSCom has been closed
[trace] Stack trace suppressed: run last js/test:executeTests for the full output.
[error] (js/test:executeTests) Exception while running JS code: scala.scalajs.runtime.UndefinedBehaviorError: An undefined behavior was detected: ReturnVal(Left(TaskId(1)),Queue(TaskScheduled(Task(TaskId(1),Do this,true)))) is not an instance of scala.util.Try (Lorg_scalajs_testinterface_internal_BridgeBase.sjsir#46)
[error] Total time: 19 s, completed Feb 2, 2015 8:32:49 PM
[jvm] $ last js/test:loadedTestFrameworks
org.mozilla.javascript.JavaScriptException: scala.scalajs.runtime.UndefinedBehaviorError: An undefined behavior was detected: ReturnVal(Left(TaskId(1)),Queue(TaskScheduled(Task(TaskId(1),Do this,true)))) is not an instance of scala.util.Try (Lorg_scalajs_testinterface_internal_BridgeBase.sjsir#46)
at org.mozilla.javascript.Interpreter.interpretLoop(Interpreter.java:1018)
at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:815)
at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:109)
at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:394)
at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3091)
at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:107)
at org.scalajs.jsenv.rhino.RhinoJSEnv$$anonfun$org$scalajs$jsenv$rhino$RhinoJSEnv$$setupCom$2$$anonfun$4.apply(RhinoJSEnv.scala:285)

Thanks in advance


On Wed, Jan 21, 2015 at 3:05 PM, Justin du coeur <jduc...@gmail.com> wrote:
On Wed, Jan 21, 2015 at 12:04 PM, SemanticBeeng . <semanticbeen...@gmail.com> wrote:
I do not see if the controllers are providing the apis the client calls or the providers of such apis are other objects (accessed with interface[]).

The latter, but you have to remember that Autowire does all sorts of automatic conversions.  So for example, this:

Client[ConversationFunctions].deleteComment(thingInfo.oid, cid).call()

Is calling *my* Client singleton with that type.  But there is Autowire in there -- that is actually a call to Client.apply[ConversationFunctions], and my Client implementation mixes in my Client trait, which is based on autowire.Client -- that is where apply() is actually defined, and it creates a proxy for the API.

Putting it more plainly: the Play controllers have *nothing whatsoever* to do with the semantics my Autowire APIs.  They are just plumbing for moving bits from the client to the server.
 
But maybe the controllers you call over the generated routers and these other apis you call over a shapeless call to Play! like done in the Spray Autowire example)?

No, absolutely not.  The only three "apis" defined at the controller level are simply for shoving bits around: userApiRequest, which routes to this user's session, commonApiRequest, for functions that don't require a user identity at all, and apiRequest, for everything else (that majority of my APIs).

You're getting all tied in knots over my Play-level code, and what I am saying is that most of that is obsolete and irrelevant.  That is the way my system *used* to work, and some vestigial bits still call that, but the *vast* majority of my client code talks only to those three entry points, which are strictly focused on routing for Autowire.  You should consider everything else to be irrelevant distractions from my POV.
 
Q: Given this, what part of the code is best to imitate to create this testing infrastructure.

I think ClientTests shows how to AutoWire client and server locally.
By "locally" I mean 

* with uPickle to test marshalling 
* without the actual remote call (all in process)

Is there a better code to look at for this goal please?

Honestly, I don't have any real recommendations for you -- your approach is so different from mine that I can't speak to this side of things.  That said, there is no difficulty using Autowire in-process: I do that a little bit, for one or two instances where it makes sense.  Keep in mind that "client" and "server" in Autowire have absolutely nothing to do with process boundaries -- it uses those terms in the usual service-architecture meaning, where the "service" is providing the functionality, and the "client" is something calling that service.  Either can be implemented anywhere you want...

SemanticBeeng .

unread,
Feb 3, 2015, 9:13:35 AM2/3/15
to Haoyi Li, scal...@googlegroups.com
Also, any trade secrets necessary to call this shared API (do_scheduleNew, etc) from a JavaScript env like real browser or Jasmine test ran in Rhino or NodeJS  (that is, outside uTest)

Asking because the API returns futures and wondering how that will work in such environments?
For example, how is the execution context passed...
Or do I simply @JsExport the classes

Any examples to share please?
Thank in advance
Nick

SemanticBeeng .

unread,
Feb 3, 2015, 9:20:42 AM2/3/15
to Haoyi Li, scal...@googlegroups.com
Lastly (?) did anyway deploy uTests calling Ajax into (say) Play!?
In other words, is something like this supposed to work from a uTest?

  def apply(method: String,
            url: String,
            data: String,
            timeout: Int,
            headers: Map[String, String],
            withCredentials: Boolean, 
            responseType: String): Future[dom.XMLHttpRequest] = {
    val ajaxReq = Map("X-Requested-With"->"XMLHttpRequest")
    val req = new dom.XMLHttpRequest()
    val promise = Promise[dom.XMLHttpRequest]

    req.onreadystatechange = {(e: dom.Event) =>
      if (req.readyState.toInt == 4){
        if ((req.status >= 200 && req.status < 300) || req.status == 304)
          promise.success(req)
        else
          promise.failure(AjaxException(req))
      }
    }
    req.open(method, url)
    req.responseType = responseType
    req.timeout = timeout
    req.withCredentials = withCredentials
    (headers ++ ajaxReq).foreach(x => req.setRequestHeader(x._1, x._2))
    req.send(data)
    promise.future

SemanticBeeng .

unread,
Feb 6, 2015, 6:42:55 PM2/6/15
to Haoyi Li, scal...@googlegroups.com
Yes, it is supposed to run with version 0.6.0, though.
Was getting errors with RC2 even

See an example

The posts the clarified how to choose wisely the SBT settings were

BTW: I wish there was a feature that allowed readers to suggest which posts should make it to an FAQ.

Nothing about "utest-js-plugin" being not needed is mentioned here 

Not complaining. Just blowing a little steam. :-)

SemanticBeeng .

unread,
Feb 6, 2015, 8:11:20 PM2/6/15
to Sébastien Doeraene, scal...@googlegroups.com
Hi Sébastien,

A big thanks for 0.6.0.
Came right in time to make my future based uTests work... (see previous post today)

Can you please let a hand with this need (below)
Need to integrate this Future based ScalaJS api with real JS running in a browser.

I need to be able to write this kind of code 

async.it('changing facility gets units', function (done) {
var facility = { id: 1 },
units = [{ id: 1, name: 'guy' }, { id: 2, name: 'something' }];
//GetUnits returns a promise that sets the units, so we need to run our expect()
//calls after that happens. Attaching a .then() to the resulting promise is the easiest
//way, since internally done() will already have been called, the tests .then()
//Handler will happen on the next tick
//If we tried to just run it synchronously after setting the facility, it would
//happen in the original tick, BEFORE the internal promise chained kicked off by the service call
var promise = Q(units);
spyOn(facilityService, 'getUnits').andCallFake(function () { return promise; });
sut.selectedFacility(facility);
promise.then(function () {
expect(facilityService.getUnits).toHaveBeenCalledWith(1);
expect(sut.units()).toBe(units);
expect(sut.selectedUnit()).toBe(null);
done();
});
});

where "promise"  would be coming from my ScalaJS API (?) and the "then" would be executing in JavaScript.

Is this possible?
My ScalaJS code will be running in integration with native JavaScript in a browser so the combination of the two needs to work for this Future based API I have.
In other words it is not a matter of just tests being able to mix the two like that but production code as well.

Where to look to figure this out?
Thinking that the generated code will return some JavaScript implementation that fits with Q.js or jQuery promises somehow?
Is @JSExport doing something special for Future based APIs to make this feasible?

Am I on the right track?
Is there an area in ScalaJS code to look at?
Any examples to share please to help with any of these points?

Thank in advance
Nick

SemanticBeeng

unread,
Feb 20, 2015, 12:59:32 AM2/20/15
to scal...@googlegroups.com, scal...@googlegroups.com
Figured this out.

I used JQueryDeferred as Promises from inside ScalaJS and this is something native JS understands


-------------
package app.modules.loans.modelproxy

import org.scalajs.jquery.{JQueryDeferred => Promise, jQuery => $}
import scala.scalajs.js.annotation.{JSExport, JSExportAll}
import framework.ModelProxy
import app.modules.loans.service.LoanService

/**
 *
 */
@JSExport
@JSExportAll
object LoansModelProxy extends ModelProxy {

  import scala.scalajs.concurrent.JSExecutionContext.Implicits.queue

  /**
   *
   */
  def listLoansForCustomer(borrowerId: String, status: String): Promise = {

    val d = $.Deferred()
    LoanService.listLoansForCustomer(borrowerId, if (status.equals("")) None else Some(status)).map { r =>

      d.resolve(() => r)

    }.recover {
      case e: Throwable => d.reject(e.getMessage)
    }
    d
  }
}
-------------
Example use from native JS


var mp = new app.modules.loans.modelproxy.LoansModelProxy()
var rp = mp.listLoansForCustomer('12', '3')
$.when(rp).then(function(data) {alert(JSON.stringify(data()))})

-------------

Any suggestions are welcome.

Nick

SemanticBeeng .

unread,
Feb 21, 2015, 10:50:56 PM2/21/15
to Sébastien Doeraene, scal...@googlegroups.com
Hi Sebastien,

I found a solution to promised based integration between ScajaJS and native JavaScript but need a bit of advice.

The code below bombs in the PromiseT constructor - this is the issue I cannot figure out.
A version of this works find if I just return the native JQueryDeferred.
But I would like to pass also the type of the data the promise is resolved with because the client code is TypeScript

To do so I created this PromiseT which extends the JQueryPromise and implements the interface by delegating to a wrapped, native JQueryDeferred.

Can you tell what is wrong or if this is wrong in some ways?

I also get compile warns like this

"Members of traits, classes and objects extending js.Any may only contain members that call js.native. This will be enforced in 1.0.
[warn]   override def always(alwaysCallbacks: js.Any*): JQueryDeferred = d.always(alwaysCallbacks)"

But this pattern seems valid to me in order to integrate between generated and native code.

Please share you wisdom on this matter.
What could be the reason for the error?
Is there a better way?
A nice solution seems to have the ScalaJS jQuery API to preserve the type parameter like the TypeScript equivalent does.

Many thanks
Nick

Example native JS client code

======
var mp = new app.modules.loans.modelproxy.OrdersModelProxy()

var rp1 = mp.ordersFor('cust1', 'InReview')
var d1 = ""
$.when(rp1).then(function(data) {alert("done!"); window.d1 = data;}, function() {alert("failed!");})

======

package app.modules.orders.modelproxy

import app.modules.orders.service.orderservice
import domain.orders.impl.{OrderI, ReturnVal}
import framework.ModelProxy
import org.scalajs.jquery.{jQuery => $, JQueryPromise, JQueryDeferred}

import scala.scalajs.js
import scala.scalajs.js.annotation.{JSExport, JSExportAll}

/**
 *
 */
class PromiseT[T /*, E :> BusinessException*/ ](d: JQueryDeferred) extends JQueryPromise {

  private var $r: ReturnVal[T] = null

  def r: ReturnVal[T] = $r

  /**
   *
   */
  def value = $r.value

  /**
   *
   */
  def ex = $r.ex

  /**
   *
   */
  def resolveT(value: ReturnVal[T]): JQueryDeferred = {
    $r = value
    d.resolve($r.asInstanceOf[js.Dynamic])
  }

  /**
   *
   */
  def rejectT(value: String): JQueryDeferred = d.reject(value.asInstanceOf[js.Dynamic])

  /**
   * Forward to 'd'
   */
  override def always(alwaysCallbacks: js.Any*): JQueryDeferred = d.always(alwaysCallbacks)

  override def done(doneCallbacks: js.Any*): JQueryDeferred = d.done(doneCallbacks)

  override def fail(failCallbacks: js.Any*): JQueryDeferred = d.fail(failCallbacks)

  override def pipe(doneFilter: js.Function1[js.Any, js.Any] = ???, failFilter: js.Function1[js.Any, js.Any] = ???, progressFilter: js.Function1[js.Any, js.Any] = ???): JQueryPromise = d.pipe(doneFilter, failFilter, progressFilter)

  override def `then`(doneCallbacks: js.Any, failCallbacks: js.Any, progressCallbacks: js.Any = ???): JQueryDeferred = d
    .`then`(doneCallbacks, failCallbacks, progressCallbacks)

 }

/**
 *
 */
@JSExport
@JSExportAll
object OrdersModelProxy extends ModelProxy {

  import scala.scalajs.concurrent.JSExecutionContext.Implicits.queue

  /**
   *
   */
  def ordersFor(customerId: String, status: String): PromiseT[List[OrderI]] = {

    val d = new PromiseT[List[OrderI]]($.Deferred())
    orderservice.ordersFor(customerId, if (status.equals("")) None else Some(status)).map { r =>

      d.resolveT(r)

    }.recover {
      case e: Throwable => d.rejectT(e.getMessage)
    }
    d
  }

  /**
   *
   */
  def loan(number: String): PromiseT[Option[OrderI]] = {

    val d = new PromiseT[Option[OrderI]]($.Deferred())

    orderservice.loan(number).map { r =>

      d.resolveT(r)

    }.recover {
      case e: Throwable => d.rejectT(e.getMessage)
    }
    d
  }

}



Sébastien Doeraene

unread,
Feb 22, 2015, 2:04:51 AM2/22/15
to SemanticBeeng, scal...@googlegroups.com

Hi,

The warnings are there for a reason: you cannot implement methods in a class extending js.Object, since they are all supposed to be implemented in js.

Why do you even have a wrapper? You can simply return the original one. TypeScript won't notice that there's no type parameter here, because all it sees is our js api, which is untyped anyway.

Now, adding proper type parameters to JQuerryDeferred would also be good.

Cheers,
Sébastien

SemanticBeeng .

unread,
Feb 22, 2015, 8:51:29 AM2/22/15
to Sébastien Doeraene, scal...@googlegroups.com
Hi, 

1. I expose a TypeScript API (not JS) since the rest of the client code is TypeScript.

2. "they are all supposed to be implemented in js.
Hmm... what is the underlying reason for forcing this?
I can see situations where ScalaJS apis exposed to JavaScript would want to return native JS objects but also mix-in other stuff from the ScalaJS side of the API.

Is there a way to do this "mix-in" today better than my attempt?
Any idea why it throws the error in the PromiseT constructor? If it did not then I could do the "mixing" from the ScalaJS side... 

I understand ScalaJS is meant to change the world of JS development but practically they will coexist.
So maybe we should consider and provide some attention to this co-habitation?

4. Is there anything special or better to do with the execution context to make this combine promises work?
I need to have this working from both real browser in prod but also native jasmine tests in PhantomJS.

5. So should I add type params to https://github.com/scala-js/scala-js-jquery?
Is it as simple as adding the type params?

Thanks
Nick

Sébastien Doeraene

unread,
Feb 22, 2015, 9:28:39 AM2/22/15
to SemanticBeeng ., scal...@googlegroups.com
Hi,

On Sun, Feb 22, 2015 at 2:51 PM, SemanticBeeng . <semanticbeen...@gmail.com> wrote:
Hi, 

1. I expose a TypeScript API (not JS) since the rest of the client code is TypeScript.

That is irrelevant. You could have type parameters in TS and not in Scala.js, or vice versa, it would still work. Type parameters are only compile-time constructs, and disappear at runtime both with TS and Scala.js. Ultimately, the level at which TS and Scala.js communicate is the untyped JS.
 
2. "they are all supposed to be implemented in js.
Hmm... what is the underlying reason for forcing this?
I can see situations where ScalaJS apis exposed to JavaScript would want to return native JS objects but also mix-in other stuff from the ScalaJS side of the API.

Is there a way to do this "mix-in" today better than my attempt?
Any idea why it throws the error in the PromiseT constructor? If it did not then I could do the "mixing" from the ScalaJS side... 

I understand ScalaJS is meant to change the world of JS development but practically they will coexist.
So maybe we should consider and provide some attention to this co-habitation?

This is a fundamental limitation of Scala.js, as it currently stands. It is impossible to write a Scala.js class that extends/implements a JS type, because that extension causes said class to be a facade type itself. You can write Scala.js classes that export members, so that they (implicitly) comply with a JS interface. Then you can soundly cast your Scala.js class to the JS interface. But the compiler will not be able to help you.
 
4. Is there anything special or better to do with the execution context to make this combine promises work?
I need to have this working from both real browser in prod but also native jasmine tests in PhantomJS.

JQueryDeferred don't use execution contexts (necessarily), so no.
 
5. So should I add type params to https://github.com/scala-js/scala-js-jquery?
Is it as simple as adding the type params?

Yes, it is as simple as that. As I said, type parameters disappear at runtime.

Cheers,
Sébastien

Reply all
Reply to author
Forward
0 new messages