Scala remote method injection - scala

I have a requirement, I have a method, which takes another function. I want to get the result of this parameter function in my caller.
I have created a code snippet for this scenario:
class ProcessHandler {
def executeInstructions(x:String=>Array[String])
{
//print the resultant list here
}
}
object ProcessHandlerMain {
def main(args: Array[String]) {
val handler = new ProcessHandler
handler.executeInstructions( instruction)
}
def instruction(x:String):Array[String] =
{
List("words", "from", "book").toArray
}
}
This call handler.executeInstructions( instruction) will be made by another process. Here I am using main method to test it out.
Here is what I do not know:
How can I print the result of parameter function
If I have to expose this method executeInstructions() to client side, what is the best approach? Here we will not be passing text instructions, rather a function similar to instruction().
Thanks
Updated: From the response received, my code is updated to
class ProcessHandler {
def executeInstructions(x:String=>Array[String])
{
//print the resultant list here
val result = x("some string here")
//this array will be sent to another service
// dispatcher.dispatch(result)
}
}
My requirements are updated:
How can I print the result of parameter function : Done
If I have to expose this method executeInstructions() to client side, what is the best approach? Here we will not be passing text instructions, rather a function similar to instruction(). Pending
The client interface has will work as below:
1. client will be calling executeInstructions() remotely and pass function as parameter.
2. InstructionId will be passed to the injected function, the resultant array will be dispatched to another service.

Related

Mocking Httpcalls always return NullPointerException

I'm trying to mock Http calls for unit test.
To do that I have done the following, I have created a RequestMock case class:
case class RequestMock() {
def sendRequest(httpRequest: HttpRequest)(implicit actorSystem: ActorSystem): Future[HttpResponse] = {
Http().singleRequest(httpRequest)
}
}
and in my service, I have written the following piece of code :
case class Service(requestHandler: RequestMock) {
....
for {
response <- {
requestHandler.sendRequest(
HttpRequest(
method = HttpMethods.GET,
uri = "http://database:9000"
)
)
} yield {
response
}
}
For the unit test, I'm trying to mock HttpCalls, to do that, I have done the following :
def test_2 = mock[RequestMock]
And for defining the mock behaviour I have done the following
when(test_2.sendRequest(
HttpRequest(
method = HttpMethods.GET,
uri = "http://database:9000")
)).thenReturn{
Future(
HttpResponse(
StatusCodes.OK,
entity = HttpEntity(ContentTypes.`text/plain(UTF-8)`,"connection established"))
But, when I execute unit tests, I always get the following error:
java.lang.NullPointerException
Does anyone know how I can solve this issue ?
A couple of problems.
First of all, test_2 should be a val, not a def.
With def like you have it, you get a different instance every time you access it. So, you define the stub on one instance, but then create your Service with a different one, that does not have sendRequest defined, so returns null by default, and that causes your NPE.
The next problem, that you will probably encounter after you fix this one is that you are not defining all of the behavior.
when(test_2.sendRequest(
HttpRequest(
method = HttpMethods.GET,
uri = "http://database:9000")
))
Only creates a stub for a method call with this specific parameter value. So, if your tests try to make a POST for example or hit a different endpoint, you'll get an NPE again.
Even if you only ever use one request, it is better to define the stub for any argument, to avoid weird NPE failures if the code happens to send a different one (you are writing a test, so should not just assume automatically, that the code will always do what you expect - you would not need the test in the first place if that was the case):
when(test2.sendRequest(any)),thenReturn(Future.successful(...))
(Note Future.successful above – that's the correct way to create Future that is immediately satisfied, what you are doing makes it run on a thread ... not a big deal in your case, but still icky).
Then, after the test code is run, you can check that the parameter value passed to the sendRequest was actually what you expect:
verify(test2)
.sendRequest(HttpRequest(method = HttpMethods.GET, uri = "http://database:9000"))

How to pass a Future data to the view?

Iam trying to get data from a web weather API, I'am getting the data by using WSClient.
Actually, I can println and visualize the data like this :
val futureResponse: Future[WSResponse] = complexRequest.get()
def weather = Action {
futureResponse.map {
response =>
println(response.json)
}
println(futureResponse)
Ok(views.html.weather("data"))
}
but I have trouble passing it to the view layer using Ok(views.html.weather("data")) cause when i println(futureResponse) its not json data it shows :
Future(Success(AhcWSResponse(StandaloneAhcWSResponse(200, OK))))
only println(response.json) shows the valid data i want to send but its unreachable outside.
You need something on the lines of
def weather = Action.async {
complexRequest.get().map(response => Ok(views.html.weather(response.json)))
}
So basically, the json is only available when the future is completed, so you can only pass it to the view inside the map function, also notice that I've used Action.async this creates an action that expects a Future[WsResponse] rather than just a WsResponse
Also bear in mind that the Futures are memoised, so if you store the reference to it in a val it will only execute once
EDIT: Fixed the future being stored in a val to avoid problems with the memoisation
It's unreachable because you will have to use a callback method to access/pass the content inside Future. That's the reason println(response.json) inside map callback shows the data/content you are interested.
You may refer to Accessing value returned by scala futures

Play Framework Search Bar

I'm trying to make a search bar with only one variable - the search input. I'm sure there's a fairly simple way to do this, but everything that I've found about getting input from the DOM (the views file) has been about using a Form and getting multiple variables. Is there a simpler way to do this if it's just a single variable?
I have a function in my Applications
def singleElement = Action { implicit request =>
val databaseSupport = new InteractWithDatabase(comm, db)
val put = Future {
while (true) {
val data = databaseSupport.getFromDatabase()
if (data.nonEmpty) {
comm.communicator ! data.head
}
}
}
Ok(views.html.singleElement)
}
I want to take some input from the user on the page singleElement and pass it into getFromDatabase which calls a MySQL query. How do I do this?
You can use restful and do something like this
routs file
GET /content/search/:search controllers.ContentController.search(search:String)
and in controller:
public Result search(String saerch) {}

Activiti Java Service Task: Passivate w/out the need for receive task

this has already been answered but the solutions have not been working out for me.
Activiti asynchronous behaviour is fairly simple and only allows the user to enable a flag which tells activiti engine to insert such task in a execution queue (managing a pool of threads).
What i want is not to insert my java service task in a pool but to passivate its behaviour and only complete such task when an external signal is received and/or a callback is called.
My attempt:
class customAsyncTask extends TaskActivityBehavior {
override def execute(execution: ActivityExecution): Unit = {
val future = Future {
println(s"Executing customAsyncTask -> ${execution.getCurrentActivityName}, ${cur}")
}
future.onComplete {
case Success(result) => leave(execution)
case _ => // whatever
}
}
def signal(processInstanceId : String, transition : String) = {
val commandExecutor = main.processEngine.getProcessEngineConfiguration.asInstanceOf[ProcessEngineConfigurationImpl].getCommandExecutor
val command = new customSignal(processInstanceId, transition)
commandExecutor.execute(command)
}
}
On my previous code sample i have registered a scala future callback which when called will terminate the current activity and move to the next.
I also have a signal method which builds a custom signal that based on the processId and a name will call execution.take with the appropriate transition.
On both cases i am getting the following error (the bottom stack changes a little)
java.lang.NullPointerException
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.take(ExecutionEntity.java:453)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.take(ExecutionEntity.java:431)
at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performOutgoingBehavior(BpmnActivityBehavior.java:140)
at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performDefaultOutgoingBehavior(BpmnActivityBehavior.java:66)
at org.activiti.engine.impl.bpmn.behavior.FlowNodeActivityBehavior.leave(FlowNodeActivityBehavior.java:44)
at org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior.leave(AbstractBpmnActivityBehavior.java:47)
Unfortunately, it is highly likely that the engine is erasing the information concerning the execution when the execute method returns, even though no complete/leave/take has been called. Even though my callback has the execution object in context, when i query for information using its proccess ID all i receive is null.
So, what i am doing wrong here? How can i achieve the behaviour that i want?
I dont see anything specific, I would have said you need to extend a class that implements SignalableActivityBehavior, but I think TaskActivityBehavior actually does this.
While the stack indicates the NPE is coming from the leave(), I am confused why leave is calling "take" since take is a transition event and really should only happen on a task labeled as synchronous.
All I can offer is, Camunda have an example implementation that is similar to your scenario. You may be able to use this to help you:
https://github.com/camunda/camunda-bpm-examples/tree/master/servicetask/service-invocation-asynchronous
It seems that activiti uses thread local variables which means that when calling methods from the scala threads (scala Executor Context) would be pointless since they do not share the context.
To solve all i have to do from my callback is make a signal call much like if i were calling from a remote system. The only difference is that i do not need to save my process instance identifier.
The code looks as such:
class AsynchronousServiceTask extends AbstractBpmnActivityBehavior {
val exec_id : String = "executionId"
override def execute(execution : ActivityExecution) = {
val future = Future { println("Something") }
future onComplete {
case _ => myobject.callSignalForMe(execution.getId)
}
}
override def signal(execution : ActivityExecution, signalName : String, signalData : AnyRef) = {
println("Signal called, leaving current activity..")
leave(execution)
}
}
Basically, myobject holds the runTimeEngine and will inject the signal in a ThreadLocal context. All clean and working as intended.

Multiple Futures in Play and using case classes to hold the future data

The scenario:
I have two different Api calls to make (across the web). ApiCall1, ApiCall2. Eventually ApiCall1 will return an Option[Catalogue] and ApiCall2 will return a Seq[Catalogue]
I then need to take these two and build a FrontPage object. During the instantiation of the FrontPage object it creates a Seq[NewProducts]. Everytime it makes a NewProduct the NewProduct must also call a MongoDB across the web inside a Future. Every Future must have completed prior to handing the FrontPage object off to the view.
Here is the code for the FrontPage class:
case class FrontPage(maybeCat1: Option[Catalogue], maybeCat2: Seq[Catalogue]) {
val newProducts:Seq[NewProduct] = {
maybeCat2.map( { cat =>
NewProduct(cat)
})
}
}
Here is the code so far for the NewProduct class:
case class NewProduct(cat:Catalogue) {
val indivProduct:Option[IndivProduct] = {
// ???
// This next line goes out to Mongo and returns a Future[List[JsObject]]
val indiv:Future[List[JsObject]] = MongoFetch.getIndivProduct(cat)
//need to strip out the 'Future', wait for it to return?
val listJS = indiv .. ???? // <-- need just the List[JsObject]]
return IndivProduct(listJs) // <-- constructs a new Option[IndivProduct]
}
}
Here is the code so far for the controller:
def landing() = Action.async {
for {
catalogue1 <- models.Granite.getCatalogue("front-page") // <- ApiCall1
catalogue2 <- models.Granite.getCatalogue("tags") // <- ApiCall2
} yield {
//??? How to now build the FrontPage object
// surely it also depends on the future?
val fp = FrontPage(catalogue1, catalogue2)
Ok(views.html.frontpage.landing(fp)) // <- at this point all futures must have returned.
}
}
I really want to be able to pass a nice neat FrontPage object to the View (and hence the designers) with a really simple set of function defined on it for them to template with. All the futures must return. Catalogue1 and Catalogue2 are not dependent on anything or even each other. Creating a Seq[NewProducts] inside the FrontPage object is depending on both of them having returned. And I can not then pass the FrontPage object to the view until it to has returned the NewProducts from Mongo.
This level of complexity is above what I am used to. I am getting confused with where and when to use for/yield comprehensions. I am afraid that this will somehow just block because the Futures are too far embedded in a case class, within a case class. The very top level of the controller is wrapped in an Async, so will this mean that any and all Futures within that Async call will be non-blocking?
See the futures as steps to get to a fully complete front page, not parts of it and think what each little part of those steps would be.
For example, to construct an instance of NewProduct, create a method that talks to the db and returns the future completed NewProduct instances.
case class NewProduct(cat:Catalogue, indiv: Option[IndivProduct])
def newProductFor(cat: Catalogue): Future[NewProduct] =
for {
listJs <- MongoFetch.getIndivProduct(cat)
} yield NewProduct(cat, IndivProduct(listJs))
You can then create your front page, again, in a function/method that handles the loading/future:
case class FrontPage(
maybeCat1: Option[Catalogue],
maybeCat2: Seq[Catalogue],
newProducts: Seq[NewProduct])
def loadFrontPage: Future[FrontPage] =
for {
catalogue1 <- models.Granite.getCatalogue("front-page")
tags <- models.Granite.getCatalogue("tags")
newProducts <- loadNewProducts(tags)
} yield FrontPage(catalogue1, tags, newProducts)
def loadNewProducts(catalogues: Seq[Catalogue]): Future[Seq[NewProduct]] = {
Future.traverse(catalogues) { catalogue =>
newProductFor(catalogue)
}
}
Note Future.traverse which takes a collection with A:s in and a function that goes from A => Future[B] and returns a Future[collection[B]].
You can then call that in an async controller to feed to a template:
def page() = Action.async {
for {
frontPage <- loadFrontPage
} yield Ok(views.some.template(frontPage))
}