I'm writing a Spray + Akka small server. And a blog post stood out and recommended this ask pattern. The CapserOk class has a signiture of this:
case class CasperOk(company: Option[Company.Company], existOrNot: Boolean)
I'm retrieving this database row and if it doesn't exist or some error occured, I want to send out a response from Spray to tell the client.
However, using this pattern, I don't know where to inject the switch.
I tried to change the code to this:
val response = (secCompanyActor ? jObjectFromCasper(company))
.mapTo[CasperOk]
.map(result => result.succeedOrNot match {
case true => (OK, "transaction successful")
case false => (Conflict, "FileLoc format is wrong or it already exists")
})
.recover{case _ => (InternalServerError, "error occured! We will fix this")}
complete(response)
Spray uses complete() to send out a HTTP response. complete() can either take two objects, or a string/serializable object. I want to use the two object mode (which allows me to manually encode its header), and an ideal situation should look like complete(response._1, response._2)
Is there any way to achieve this with Akka's Future?
You can achieve this via registering a call to complete function on future onComplete method.
response.onComplete {
case (statusCode, message) => complete(statusCode, message)
}
Related
Can anyone explain how and when to use ActorIdentity with a good example?
From documents I can find that "There is a built-in Identify message that all Actors will understand and automatically reply to with a ActorIdentity message containing the ActorRef".
Does that statement mean obtained actor say actorSelector have ActorIdentity message wrapped in my actor?
ActorSelection actorSelector = getContext().actorSelection("/A/B/*");
When you send an Identify message to an ActorSelection the actor will respond, if it exists, with an ActorIdentity message.
If the actor exists the ActorIdentity message will contain a Some(actorRef). It is more efficient to send messages to ActorRefs than ActorSelections.
For example (from the manual):
class Follower extends Actor {
val identifyId = 1
context.actorSelection("/user/another") ! Identify(identifyId)
def receive = {
case ActorIdentity(`identifyId`, Some(ref)) =>
context.watch(ref)
context.become(active(ref))
case ActorIdentity(`identifyId`, None) => context.stop(self)
}
def active(another: ActorRef): Actor.Receive = {
case Terminated(`another`) => context.stop(self)
}
}
The section in the manual that covers this is called Identifying Actors via Actor Selection.
One of the features of Akka HTTP (formally known as Spray) is its ability to automagically marshal and unmarshal data back and forth from json into case classes, etc. I've had success at getting this to work well.
At the moment, I am trying to make an HTTP client that performs a GET request with query parameters. The code currently looks like this:
val httpResponse: Future[HttpResponse] =
Http().singleRequest(HttpRequest(
uri = s"""http://${config.getString("http.serverHost")}:${config.getInt("http.port")}/""" +
s"query?seq=${seq}" +
s"&max-mismatches=${maxMismatches}" +
s"&pam-policy=${pamPolicy}"))
Well, that's not so pretty. It would be nice if I could just pass in a case class containing the query parameters, and have Akka HTTP automagically generate the query parameters, kind of like it does for json. (Also, the server side of Akka HTTP has a somewhat elegant way of parsing GET query parameters, so one would think that it would also have a somewhat elegant way to generate them.)
I'd like to do something like the following:
val httpResponse: Future[HttpResponse] =
Http().singleRequest(HttpRequest(
uri = s"""http://${config.getString("http.serverHost")}:${config.getInt("http.port")}/query""",
entity = QueryParams(seq = seq, maxMismatches = maxMismatches, pamPolicy = pamPolicy)))
Only, the above doesn't actually work.
Is what I want doable somehow with Akka HTTP? Or do I just need to do things the old-fashioned way? I.e, generate the query parameters explicitly, as I do in the first code block above.
(I know that if I were to change this from a GET to a POST, I could probably to get it to work more like I would like it to work, since then I could get the contents of the POST request automagically converted from a case class to json, but I don't really wish to do that here.)
You can leverage the Uri class to do what you want. It offers multiple ways to get a set of params into the query string using the withQuery method. For example, you could do something like this:
val params = Map("foo" -> "bar", "hello" -> "world")
HttpRequest(Uri(hostAndPath).withQuery(params))
Or
HttpRequest(Uri(hostAndPath).withQuery(("foo" -> "bar"), ("hello" -> "world")))
Obviously this could be done by altering the extending the capability of Akka HTTP, but for what you need (just a tidier way to build the query string), you could do it with some scala fun:
type QueryParams = Map[String, String]
object QueryParams {
def apply(tuples: (String, String)*): QueryParams = Map(tuples:_*)
}
implicit class QueryParamExtensions(q: QueryParams) {
def toQueryString = "?"+q.map{
case (key,value) => s"$key=$value" //Need to do URL escaping here?
}.mkString("&")
}
implicit class StringQueryExtensions(url: String) {
def withParams(q: QueryParams) =
url + q.toQueryString
}
val params = QueryParams(
"abc" -> "def",
"xyz" -> "qrs"
)
params.toQueryString // gives ?abc=def&xyz=qrs
"http://www.google.com".withParams(params) // gives http://www.google.com?abc=def&xyz=qrs
OK, I think there's no easy (make that lazy) way to do what I want but given the Perl SOAP::Transport::HTTP::CGI code fragment below what I am looking to do is intercept all SOAP operation passing through the service and log the result of an operation or fault...
SOAP::Transport::HTTP::CGI
-> dispatch_to(
#first arg needs to be the directory holding the PackageName.pm modules with no trailing "/". The args aftre the first are name of SPECIFIC packages to be loaded as needed by SOAP requests
#Failure to call out specific moudules below will allow the external SOAP modules to be loaded, but the overall module #INC path for other Perl modules will be blocked for security reasons
SOAP_MODULE_INCULDE, #name of the directory holding the PackageName.pm modules with no trailing "/"
"TechnicalMetaDataExtraction", #prod - wrapper for EXIFTool
"Ingest", #module (package) name
"ImageManipulation", #module (package) name
"FacebookBroadcast", #unfinished
"CompressDecompress", #unfinished
"ImageOCR", #prod - tesseract
"HandleDotNet", #prod
"Pipeline", #prod (needs work)
"TwitterBroadcast", #prototype
"Messaging", #prototype but text format email works
"Property", #development
"FileManager", #prototype
"PassThrough" #prod - module to do location conversion (URL -> Fedora Obj+DS, Fedora Obj+DS -> file, URL -> InlineBase64, etc.) but format conversion
) #done with the dispacth_to section
-> on_action(sub {
#on_action method lets you specify SOAPAction understanding. It acceptsreference to subroutine that takes three parameters: SOAPAction, method_uri and method_name.
#'SOAPAction' is taken from HTTP header and method_uri and method_name are extracted from request's body. Default behavior is match 'SOAPAction' if present and ignore it otherwise.
#die SOAP::Data->type('string')->name('debug')->value("Intercepted call, SOAP request='".shift(#_)."'");
if($Debug) {
##_ notes:
#[0] - "http://www.example.org/PassThrough/NewOperation"
#[1] - http://www.example.org/PassThrough/
#[2] - NewOperation
#[3] - "undefined"
my %DataHash=(
message => #_[0]
);
#SendMessageToAMQTopic(localtime()." - ".#_[0]);
SendDebugMessage(\%DataHash, "info");
} #there's only one element passed at this level
}) #end on_action
#-> on_debug() #not valid for SOAP::Transport::HTTP::CGI
#-> request() #valid, but does not fire - request method gives you access to HTTP::Request object which you can provide for Server component to handle request.
#-> response() #does not fire - response method gives you access to HTTP::Response object which you can access to get results from Server component after request was handled.
#-> options({compress_threshold => 10000}) #causes problems for the JavaScript soap client - removed for the moment
-> handle() #fires but ignores content in sub - handle method will handle your request. You should provide parameters with request() method, call handle() and get it back with response().
;
Initially I thought I could get the information I needed from the "on_action" method, but that only contains the destination of the SOAP call (before it is sent?) and I'm looking for data in the operation result that will be sent back to the SOAP client. The documentation of "SOAP::Transport::HTTP::CGI" is a bit thin and there are few examples online.
Anyone know if this is possible give the what the code above is set up? If not, then the only other option is to alter each method of my SOAP service code modules to include the "SendDebugMessage" function.
I would suggest subclassing SOAP::Transport::HTTP::CGI and hooking into the handle() method. An untested and probably non-working example would be:
package MySoapCGI;
use Data::Dumper;
use SOAP::Transport::HTTP;
use base 'SOAP::Transport::HTTP::CGI';
sub handle {
my $self = shift;
$self->SUPER::handle(#_);
warn Dumper($self->request);
warn Dumper($self->response);
}
Replace the dumpers with whatever logging you want. You may need to do some XML parsing, because these will be the raw HTTP::Request and HTTP::Response.
I've found a few questions and pages dealing with cookies in Symfony2 but there doesn't seem to be any clear consensus on exactly how this is supposed to work. I can, of course, just fall back to using PHP's native setcookie function but I feel that it should be an easy thing to do with Symfony2 as well.
I have an action in my controller from which I simply want to return a view with a cookie attached. Thus far I have seem examples basically like this:
use Symfony\Compentnt\HttpFoundation\Response;
public function indexAction() {
$response = new Response();
$response->headers->setCookie(new Cookie('name', 'value', 0, '/');
$response->send();
}
The problem with this is that it sends the response... and doesn't render the view. If I set the cookie without sending the headers the view is rendered but the header (cookie) is not sent.
Poking around I found the sendHeaders() method in the Response object so I'm now manually calling that in my action before returning and that seems to work:
public function indexAction() {
...
$response->sendHeaders();
return array('variables' => 'values');
}
But is this really the expected pattern to use? In previous versions of symfony I could set the headers in my controller and expect the view controller to handle sending whatever I had sent. It seems now that I must manually send them from the action to get it to work, meaning I have to call this from any action that I set headers in. Is this the case or is there something that I'm missing that's so obvious that no one has bothered to even mention it in any of the documentation?
I think you're on the right lines with:
$response->headers->setCookie(new Cookie('name', 'value', 0, '/'));
If you're trying to render a template then check out the docs here:
Symfony2 Templating Service
If you look at the line:
return $this->render('AcmeArticleBundle:Article:index.html.twig');
basically the render method is returning a response (which the controller then returns) which has the content of the twig template, all you have to do is intercept this:
$response = $this->render('AcmeArticleBundle:Article:index.html.twig');
$response->headers->setCookie(new Cookie('name', 'value', 0, '/'));
return $response;
I think that's it anyway...
I'm just starting to practice BDD using the GWT approach to the following code exert and just realised that I can't do the second test.
My GWT goes something like
Given there exists an open query
When the user replies to the query
Then it should save the reply if the reply is not blank
Then it should notify the user and not save the reply if it is blank
So I coded it up like so
public class when_user_replies_to_the_query : OpenQuery
{
Because
{
query.Reply(data);
}
ThenIt should_save_the_reply_to_the_database_if_there_is_a_reply
ThenIt should_notify_the_user_if_there_is_no_text_in_the_reply_and_not_save_to_database
}
public class Query
{
void Reply(string data)
{
//do something
}
}
But then I realised that I can't do the second case because the first case requires data to have something in it whilst the second case says that data should be an empty string.
Does this mean that I should be splitting my GWT into something like
Given the reply is blank
When the user replies to the query
Then it should notify the user ......
If this is the case, then I'd be writing a huge amount of null case scenarios for return
values being null. Such as
Given the database is null
When retrieving queries
Should reply with error message
When saving queries
Should save to file and reply with error message
When // basically doing anything
Should //give appropriate response
Is this how I should be writing my BDD specs? And am I even in the right forum O_O?
You would want to invert the two Then clauses, because they basically form different contexts under which the Query class is exercised. When you read both Then statemenents you can see that "if is not blank" and "is blank" form both contexts.
Context #1:
Given an open query
Given a non-blank reply
When the user replies to the query
It should save the reply
public class When_the_user_replies_to_the_query_and_the_reply_is_not_blank
{
static Query Query;
Establish context = () =>
{
Query = new Query();
};
Because of = () =>
{
Query.Reply("answer");
};
It should_save_the_reply = () =>
{
// Use your imagination
};
}
Context #2:
Given an open query
Given a blank reply
When the user replies to the query
It should not save the reply
It should notify the user
public class When_the_user_replies_to_the_query_and_the_reply_is_blank
{
static Query Query;
Establish context = () =>
{
Query = new Query();
};
Because of = () =>
{
Query.Reply(String.Empty);
};
It should_not_save_the_reply = () =>
{
// Use your imagination
};
It should_notify_the_user = () =>
{
// Use your imagination
};
}
Considering that you could have multiple possible "empty reply" values (null, String.Empty, " ", \r\n) , you could write contexts for any of these. I often do not write specs for any imaginable combination of values, but rather
have one context for the "happy path", i.e. reply is not empty
have one context for empty replies
In the light of your example, one could argue that the Query class isn't the right place to decide whether a reply satisfies the "is not empty" specification. You should rather code up that decision in a separate class and the Query should rely on the decision of that one. This would bring some advantages:
Separation of concerns: the Query class and the specification can evolve separately
You can re-use the specification in multiple places, hinting a problem with the reply before the user posts his empty reply
You can get the specification under test separately without worrying about user notification and database saves, thus preventing context explosion for Query concerns