Roland, 

I am doing that with the low level API right now and it mostly works. Its 
just unfortunate I dont have access to the tools in the DSL inside the 
actor because my paths to validation of the logic are quite a bit more rich 
than a simple determination of whether the attribute is present in the 
call. Whether the attribute is truly needed or not often depends on 
context. Like I said it owuld be awesome if inside the actor I could 
re-enter the dsl in the manner i described in the OP. 

The good news is the low level API is pretty good but it would be nice if I 
could use some of the tools for pulling out request bodies as json and so 
on. 

-- Robert

On Monday, April 3, 2017 at 2:05:59 PM UTC-5, rkuhn wrote:
>
> Hi Robert,
>
> since a Route is just a function from request to future of response you 
> can easily achieve all that you describe, delegating as much or as little 
> as you wish to actors via the ask pattern (delegating via a parent actor 
> whose ref is known to the route). Commonly extracted metadata are 
> conveniently factored out into custom or composed directives and the actor 
> may respond with HttpResponse for full flexibility in terms of determining 
> the success of the request.
>
> Unfortunately, I am traveling and not at my computer, hence no code.
>
> Regards, Roland 
>
> Sent from my iPhone
>
> On 3 Apr 2017, at 19:20, kraythe <kra...@gmail.com <javascript:>> wrote:
>
> Yes I know routes can be concatenated from several sources. I addressed 
> that in my original post. It doesn't take away from the core thrust. Even 
> the determination of whether an endpoint ends up in a bad request or an ok 
> or a forbidden could take a significant amount of logic to determine in the 
> real world and some of that logic may be a result of aggregating data from 
> several actors which cant be done in a route without ask pattern and then 
> you are back in imperative programming and there is little point to using 
> actors at all. 
>
> On Monday, April 3, 2017 at 11:00:49 AM UTC-5, Rob Wills wrote:
>>
>> If you have lots of endpoints and you want to split them up into multiple 
>> files you can do that using the dsl.  
>>
>>
>> http://stackoverflow.com/questions/34514372/akka-http-with-multiple-route-configurations/34516168#34516168
>>
>> I don't think your proposal is a good idea.
>>
>> On Mon, Apr 3, 2017 at 4:52 PM, 'Ryan Tanner' via Akka User List <
>> akka...@googlegroups.com> wrote:
>>
>>> Leaving aside the tone of this post...
>>>
>>> Have you looked at the longer example of the DSL?
>>>
>>>
>>> http://doc.akka.io/docs/akka-http/current/scala/http/routing-dsl/index.html#longer-example
>>>
>>> It has examples of how to delegate an endpoint's business logic off to 
>>> actors or futures.
>>>
>>>
>>> On Sunday, April 2, 2017 at 7:09:32 PM UTC-6, kraythe wrote:
>>>>
>>>> I was really excited about akka-http as I would be able to unburden my 
>>>> code from the baggage of play and handle my server side as a pure akka 
>>>> actors app but unless I am much mistaken something is dreadfully amiss 
>>>> with 
>>>> the implementation. 
>>>>
>>>> One of the main core features is the actor paradigm and the integration 
>>>> of a rich actor system. However, the preferred approach to akka-http seems 
>>>> to be a throwback to one file programming. The main reason it seems this 
>>>> way is the DSL. Take this example from a tutorial: 
>>>>
>>>>  path("bank" / IntNumber) { id =>
>>>>         get {
>>>>           complete {
>>>>             getById(id).map{result =>
>>>>               if(result.isDefined)
>>>>                   HttpResponse(entity =write(result.get))
>>>>               else
>>>>                 HttpResponse(entity ="This bank does not exist")
>>>>             }
>>>>
>>>>
>>>>           }
>>>>         }
>>>>       }~
>>>>         path("bank" / "update") {
>>>>           post {
>>>>             entity(as[String]) { bankJson =>
>>>>               complete {
>>>>                 val bank =parse(bankJson).extract[Bank]
>>>>                 update(bank).map{result => HttpResponse(entity ="Bank 
>>>> has  been updated successfully")}
>>>>               }
>>>>             }
>>>>           }
>>>>         }
>>>>     }
>>>>   }
>>>>
>>>>
>>>> Simple enough right? Too me I see the start of an anti-pattern but lets 
>>>> look further. It gets worse though, quickly,  as shown in the akka-http 
>>>> documentation here 
>>>> <http://doc.akka.io/docs/akka-http/10.0.0/scala/http/routing-dsl/index.html#longer-example>.
>>>>  
>>>> Still not bothered? The problem is that these examples are shallow and not 
>>>> rooted in the real world. In the bank application above would be hundreds 
>>>> of endpoints and each endpoint would have to validate data send by the 
>>>> user, check to see whether that data correct against the database and a 
>>>> dozen other things that would alter the nature of the return type to a  
>>>> bad 
>>>> request or internal error. The banking app would also have to log the 
>>>> problems so forensics can be done on malicious users. Just taking one 
>>>> route 
>>>> "deposit" would be several hundred lines of code INSIDE the route. 
>>>> However, 
>>>> it seems that there is no way to break off the route, offload it to 
>>>> another 
>>>> component (such as a Per Request Actor) and then continue the DSL where 
>>>> you 
>>>> left off. I had the chance to see for an app in another company that was 
>>>> asking my advice and their route is 12k lines long and at one point nested 
>>>> 30 levels deep.
>>>>
>>>> Now I know what you might say, "But Robert, you can break up the route 
>>>> into multiple files" which is true but something has to manually 
>>>> concatenate all of those routes together and they cant be done off of the 
>>>> main route. once you are in the routes DSL you are stuck there. Sure, you 
>>>> can call an actor with a future to do a completion but that actor itself 
>>>> might return data that requires a different kind of completion based upon 
>>>> certain criteria such as whether the user has had their account suspended. 
>>>> So if your completions are diverse, how do you break up the route? 
>>>>
>>>> Now if someone has answers to these issues I would love to hear them 
>>>> but after researching I found that basically PRA's are deprecated in favor 
>>>> of a "convenient" DSL that entraps the user. For my purposes I opted to go 
>>>> with the low level API and factor off the route dispatching to a routing 
>>>> actor (yes, I know this is what the materializer does) and then just pull 
>>>> out route data the old fashioned way. My router,  does path checking and 
>>>> then dispatches to another actor to handle that specific request and then 
>>>> sends the HttpResponse entity back to the sender which completes the ask 
>>>> and the route. My startup looks like this: 
>>>>
>>>>   val serverSource: Source[Http.IncomingConnection, Future[Http.
>>>> ServerBinding]] =
>>>>     Http().bind(interface = "localhost", port = 8080)
>>>>   log.info("Server online at http://localhost:8080";)
>>>>   val bindingFuture: Future[Http.ServerBinding] =
>>>>     serverSource.to(Sink.foreach { connection => // foreach 
>>>> materializes the source
>>>>       import akka.pattern.ask
>>>>       println("Accepted new connection from " + connection.
>>>> remoteAddress)
>>>>       connection.handleWithAsyncHandler(request => (httpRouter ? 
>>>> request).mapTo[HttpResponse], parallelism = 4)
>>>>     }).run()
>>>>
>>>>
>>>> A snippet of the router looks like this. 
>>>>
>>>> class HttpRequestRouter extends Actor {
>>>>   protected val log = Logging(context.system, this)
>>>>
>>>>
>>>>   override def receive: Receive = {
>>>>     case request: HttpRequest =>
>>>>       val requestId = UUID.randomUUID()
>>>>       request match {
>>>>          case HttpRequest(GET, Uri.Path("/"), _, _, _) =>
>>>>           notFound(requestId, request) // todo Implement this
>>>>         case HttpRequest(POST, Uri.Path("/hello"), _, _, _) =>
>>>>           invokeActor(classOf[HelloActor], requestId, request)
>>>>         case HttpRequest(GET, Uri.Path("/users"), _, _, _) =>
>>>>           invokeActor(classOf[ListUsersActor], requestId, request)
>>>>         case HttpRequest(GET, Uri.Path("/addUser"), _, _, _) =>
>>>>           invokeActor(classOf[AddUserActor], requestId, request)
>>>>          case uri =>
>>>>           notFound(requestId, request)
>>>>       }
>>>>     case msg => log.warning("Received unknown message: {}", msg)
>>>>   }
>>>>
>>>>
>>>>   private def invokeActor(actorType: Class[_], requestId: UUID, request
>>>> : HttpRequest) = {
>>>>     context.actorOf(Props(actorType, sender(), requestId, request), 
>>>> requestId.toString)
>>>>   }}
>>>>
>>>> This allows me to fork off PRAs as needed but it kind of stinks in one 
>>>> way because there are a lot of tools in the DSL for unpacking entities and 
>>>> so on that I cant use, or rather if there is a way I and neither I nor 
>>>> anyone within the reach of google has figured it out. 
>>>>
>>>> So what am I missing? Do people really love this monstrous DSL even 
>>>> though in a 100 endpoint system the thing will be gargantuan? Is there a 
>>>> means to fork off at any point in the DSL and then "reboot the stream"? It 
>>>> would be nice if some of the DSL tools could be invoked arbitrarily inside 
>>>> the PRAs on the request object like. 
>>>> class OrderPRA(replyTo: ActorRef, requestId: UUID, request: HttpRequest
>>>> ) {
>>>>
>>>>   // ... code
>>>>   sender.tell(withRequest(request) {
>>>>     entity(as[Order]) { order =>
>>>>             complete {
>>>>               // ... write order to DB
>>>>               "Order received"
>>>>             }
>>>>           }
>>>>   }), self)
>>>> }
>>>>
>>>>
>>>> Opinions? Thoughts?
>>>>
>>>>
>>>>
>>>>
>>>> -- 
>>> >>>>>>>>>> Read the docs: http://akka.io/docs/
>>> >>>>>>>>>> Check the FAQ: 
>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>> >>>>>>>>>> Search the archives: 
>>> https://groups.google.com/group/akka-user
>>> --- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "Akka User List" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to akka-user+...@googlegroups.com.
>>> To post to this group, send email to akka...@googlegroups.com.
>>> Visit this group at https://groups.google.com/group/akka-user.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>> -- 
> >>>>>>>>>> Read the docs: http://akka.io/docs/
> >>>>>>>>>> Check the FAQ: 
> http://doc.akka.io/docs/akka/current/additional/faq.html
> >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Akka User List" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to akka-user+...@googlegroups.com <javascript:>.
> To post to this group, send email to akka...@googlegroups.com 
> <javascript:>.
> Visit this group at https://groups.google.com/group/akka-user.
> For more options, visit https://groups.google.com/d/optout.
>
>

-- 
>>>>>>>>>>      Read the docs: http://akka.io/docs/
>>>>>>>>>>      Check the FAQ: 
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>>      Search the archives: https://groups.google.com/group/akka-user
--- 
You received this message because you are subscribed to the Google Groups "Akka 
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to akka-user+unsubscr...@googlegroups.com.
To post to this group, send email to akka-user@googlegroups.com.
Visit this group at https://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to