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.
controllers.Application.apiRequest(userName, spaceId).callAjax("pickledRequest" -> request)
--
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.
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, etcSee more https://www.evernote.com/shard/s175/sh/ce94f122-efd2-41ee-93b2-429a489278ba/3c4557222348385aWhat does "bad" mean in terms of one being able to use this existing support?
2. utest seems to support async testsReferencesQ: 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)ReferencesQ: Does utest mean to support testing such APs?
4. Autowire also uses Futures.Q: Does utest support testing such APIs? Any examples handy?
FinallyQ: 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])?
Just wondering: What are some of the limitations in terms of classes you can represent that you have encountered?
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.)
--
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/CAGJkGJ-rDUT9FqWgZMPCcjnwNE1DbTB3d2CbM%2B7Ky2xx6QA0GQ%40mail.gmail.com.
Looks like the effort I put into making autowire stand-alone has paid off ^_^
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, etcSee more https://www.evernote.com/shard/s175/sh/ce94f122-efd2-41ee-93b2-429a489278ba/3c4557222348385aWhat 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.
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.
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
--
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/CAPkb-7Bn5kkxerhgYRVBbadDx7Sb%2BGODhCYgDmoTw2ffvphrKA%40mail.gmail.com.
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.
(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.
well, may not be able to write all code in Scala.JS
plus we lose JavaScript developers
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.JSI 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.
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?
So if I want to use the JSExported code to write BDD/async/promise code like thisthen 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?
So if I want to use the JSExported code to write BDD/async/promise code like thisthen 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 means1. in uTest I have the typesafety2. 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:
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 api1. 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
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
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...
Yes, that's right.SébastienOn 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 muchNick
| @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. |
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 likecontrollers.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 AutoWire1. On the client I still have to worry about handcrafting the Ajax call: urls, get, post, etcWith PLay! generated routers this is done for meoverride def doCall(req: Request): Future[String] = {print(req.path)url = "/api/" + req.path.mkString("/"),data = upickle.write(req.args)).map(_.responseText)}2. On the serverpost {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?On Monday, January 12, 2015 at 7:54:41 AM UTC-5, Justin du coeur wrote: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.ThanksNickI'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.
To view this discussion on the web visit https://groups.google.com/d/msgid/scala-js/8fcc7398-02ce-40e5-947f-e4f127e8e171%40googlegroups.com.
Reviewed more of this Justin. It will help me, thank you.In https://github.com/jducoeur/Querki/blob/master/querki/scalajs/src/main/scala/querki/comm/ClientRoutes.scala you said"
@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?
| "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 | |
| } | |
| } |
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...
| 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(); | |
| }); | |
| }); |
Nick
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
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?