Skip to content

Commit

Permalink
#1434 using map for request params
Browse files Browse the repository at this point in the history
  • Loading branch information
naleeha authored and keikeicheung committed Sep 5, 2024
1 parent 065ea84 commit ce4ab99
Show file tree
Hide file tree
Showing 14 changed files with 199 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import org.finos.vuu.core.table.TableContainer;
import org.finos.vuu.net.rpc.*;

import java.util.Arrays;

/* Work in Progress - do not use this as example yet
* */
public class PersonRpcHandler extends DefaultRpcHandler {
Expand All @@ -19,20 +17,21 @@ public PersonRpcHandler(DataTable table, TableContainer tableContainer) {
typeAheadHandler.register();

registerRpc("UpdateName", (params) -> processUpdateNameRpcRequest(params));
registerRpc("GetPeopleWithName", (params) -> processGetPeopleNameRpcRequest(params));
registerRpc("GetAccountId", (params) -> processGetAccountIdRpcRequest(params));
}

public RpcFunctionResult processUpdateNameRpcRequest(RpcParams params) {
updateName(
params.namedParams().get("Id").get().toString(), //how to report error when expected param missing or fail to cast to right type
params.namedParams().get("Name").get().toString()
);
return new RpcFunctionSuccess(); //how to control what viewport action to trigger?

var paramData = params.namedParams();
// UpdateNameRequestParam x = (UpdateNameRequestParam) paramData;
// updateName(x.Id(), x.Name());
updateName(paramData.get("Id").get().toString(), paramData.get("Name").get().toString());
return new RpcFunctionSuccess(); //how to control what viewport action to t rigger?
}

public RpcFunctionResult processGetPeopleNameRpcRequest(RpcParams params) {
var people = getPeopleWithNameThatStartWith(
Arrays.stream(params.params()).findFirst().toString()
public RpcFunctionResult processGetAccountIdRpcRequest(RpcParams params) {
var people = getAccountId(
params.namedParams().get("rowKey").get().toString()
);
return new RpcFunctionSuccess(people); //need to return result
}
Expand All @@ -43,8 +42,10 @@ public String[] updateName(String id, String newName) {
return new String[0];
}

public String[] getPeopleWithNameThatStartWith(String search) {
return new String[0];
public int getAccountId(String rowKey) {
var rowData = this.table.pullRow(rowKey);
var accountNumber = (int) rowData.get("Account");
return accountNumber;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.finos.vuu.person;

import java.io.Serializable;

public class UpdateNameRequestParam implements Serializable {
private String id;
private String name;

public UpdateNameRequestParam(String id, String name){
this.id = id;
this.name = name;
}

public String Id() {return id;}
public String Name() {return name;}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.finos.vuu.person.manual;

public class TestParam {
public Object Id;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package org.finos.vuu

import org.finos.toolbox.time.DefaultClock
import org.finos.vuu.core.module.{TableDefContainer, ViewServerModule}
import org.finos.vuu.module.JavaExampleModule
import org.finos.vuu.net._
import org.finos.vuu.viewport.{ViewPortRange, ViewPortTable}
import org.finos.vuu.wsapi.WebSocketApiTestBase

class PersonRpcHandlerWSApiTest extends WebSocketApiTestBase {

private val tableName = "PersonManualMapped"
private val moduleName = JavaExampleModule.NAME

Feature("[Web Socket API] Person Rpc Test") {
Scenario("Type ahead for a column") {

Given("a view port exist")
val viewPortId: String = createViewPort

When("request typeahead for Name column")
val getTypeAheadRequest = createTypeAheadRequest(viewPortId, "PersonManualMapped", "Name")
val requestId = vuuClient.send(sessionId, tokenId, getTypeAheadRequest)

Then("return unique values in that column")
val response = vuuClient.awaitForResponse(requestId)

val responseBody = assertBodyIsInstanceOf[RpcResponseNew](response)
responseBody.rpcName shouldEqual "getUniqueFieldValues"

val result = assertAndCastAsInstanceOf[RpcSuccessResult](responseBody.result)
result.data shouldEqual List("Adam", "Natalie")

And("return No Action")
responseBody.action shouldBe a[NoneAction]
}

Scenario("Custom Rpc request with a reference type as param") {

Given("a view port exist")
val viewPortId: String = createViewPort

When("request GetAccountId given the row key")
val getTypeAheadRequest = RpcRequest(
ViewPortContext(viewPortId),
"GetAccountId",
params = Map("rowKey" -> "uniqueId1"))
val requestId = vuuClient.send(sessionId, tokenId, getTypeAheadRequest)

Then("return account number for person with that id")
val response = vuuClient.awaitForResponse(requestId)

val responseBody = assertBodyIsInstanceOf[RpcResponseNew](response)
responseBody.rpcName shouldEqual "GetAccountId"

val result = assertAndCastAsInstanceOf[RpcSuccessResult](responseBody.result)
result.data shouldEqual 56440

And("return No Action")
responseBody.action shouldBe a[NoneAction]
}


Scenario("Custom Rpc request with object as params") {

Given("a view port exist")
val viewPortId: String = createViewPort


When("request update name")
val getTypeAheadRequest = RpcRequest(
ViewPortContext(viewPortId),
"UpdateName",
params = Map("Id" -> "uniqueId1", "Name" -> "Chris"))
val requestId = vuuClient.send(sessionId, tokenId, getTypeAheadRequest)

Then("return success response")
val response = vuuClient.awaitForResponse(requestId)

val responseBody = assertBodyIsInstanceOf[RpcResponseNew](response)
responseBody.rpcName shouldEqual "UpdateName"

val result = assertAndCastAsInstanceOf[RpcSuccessResult](responseBody.result)

And("return No Action")
responseBody.action shouldBe a[NoneAction]

And("return row update with new name")
}
}

override protected def defineModuleWithTestTables(): ViewServerModule =
new JavaExampleModule().create(new TableDefContainer(), new DefaultClock())


private def createViewPort = {
val createViewPortRequest = CreateViewPortRequest(ViewPortTable(tableName, moduleName), ViewPortRange(1, 100), columns = Array("Id", "Name"))
vuuClient.send(sessionId, tokenId, createViewPortRequest)
val viewPortCreateResponse = vuuClient.awaitForMsgWithBody[CreateViewPortSuccess]
val viewPortId = viewPortCreateResponse.get.viewPortId
viewPortId
}


private def createTypeAheadRequest(viewPortId: String, tableName: String, columnName: String): RpcRequest = {
RpcRequest(
ViewPortContext(viewPortId),
RpcNames.UniqueFieldValuesRpc,
params = Map(
"table" -> tableName,
"module" -> moduleName,
"column" -> columnName
))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ class CoreServerApiHandler(val viewPortContainer: ViewPortContainer,
}
case Failure(e) =>
logger.info(s"Failed to process VP RPC call ${ctx.requestId}", e)
createErrorRpcResponse(msg, e.getMessage)
createErrorRpcResponse(msg, e.toString)
}
vsMsg(response)(ctx)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,28 @@ class MyTypeAheadHandler(rpcRegistry: DefaultRpcHandler, tableContainer: TableCo
}

def processGetUniqueFieldValuesRequest(params: RpcParams): RpcFunctionResult = {

val inputParam = params.namedParams

val values = getUniqueFieldValues(
params.namedParams("table").toString, //how to report error when expected param missing or fail to cast to right type
params.namedParams("module").toString,
params.namedParams("column").toString,
inputParam("table").toString, //how to report error when expected param missing or fail to cast to right type
inputParam("module").toString,
inputParam("column").toString,
params.viewPortColumns.get,
null //todo what to do about request context
)
new RpcFunctionSuccess(values)
}

def processGetUniqueFieldValuesStartWithRequest(params: RpcParams): RpcFunctionResult = {

val inputParam = params.namedParams

val values = getUniqueFieldValuesStartingWith(
params.namedParams("table").toString, //how to report error when expected param missing or fail to cast to right type
params.namedParams("module").toString,
params.namedParams("column").toString,
params.namedParams("starts").toString,
inputParam("table").toString, //how to report error when expected param missing or fail to cast to right type
inputParam("module").toString,
inputParam("column").toString,
inputParam("starts").toString,
params.viewPortColumns.get,
null //todo what to do about request context
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ViewPortTypeAheadRpcHandler(tableContainer: TableContainer) extends Defaul

def processGetUniqueFieldValuesRequest(params: RpcParams): RpcFunctionResult = {

val inputParam = params.data.get.asInstanceOf[Map[String, Any]]
val inputParam = params.namedParams

val values = getUniqueFieldValues(
inputParam("table").toString, //how to report error when expected param missing or fail to cast to right type
Expand All @@ -27,7 +27,7 @@ class ViewPortTypeAheadRpcHandler(tableContainer: TableContainer) extends Defaul

def processGetUniqueFieldValuesStartWithRequest(params: RpcParams): RpcFunctionResult = {

val inputParam = params.data.get.asInstanceOf[Map[String, Any]]
val inputParam = params.namedParams

val values = getUniqueFieldValuesStartingWith(
inputParam("table").toString, //how to report error when expected param missing or fail to cast to right type
Expand Down
2 changes: 1 addition & 1 deletion vuu/src/main/scala/org/finos/vuu/net/Messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ case class RowUpdate(vpVersion: String, viewPortId: String, vpSize: Int, rowInde
* New api for websocket messages - work in progress
*/

case class RpcRequest(context: RpcContext, rpcName: String, params: Any) extends MessageBody
case class RpcRequest(context: RpcContext, rpcName: String, params: Map[String, Any]) extends MessageBody

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes(Array(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class DefaultRpcHandler extends RpcHandler with StrictLogging {
val namedPars = rpc.namedParams
val module = Option(msg).map(_.module).getOrElse("")

processRpcMethodHandler(method, new RpcParams(params, namedPars, None, None, ctx)) match {
processRpcMethodHandler(method, new RpcParams(params, namedPars, None, ctx)) match {
case result: RpcFunctionSuccess => Some(VsMsg(ctx.requestId, ctx.session.sessionId, ctx.token, ctx.session.user, RpcResponse(method, result.optionalResult.orNull, error = null), module))
case error: RpcFunctionFailure => Some(VsMsg(ctx.requestId, ctx.session.sessionId, ctx.token, ctx.session.user, RpcResponse(rpc.method, null, Error(error.error, error.code)), module))
}
Expand All @@ -57,7 +57,7 @@ class DefaultRpcHandler extends RpcHandler with StrictLogging {
} catch {
case e: Exception =>
logger.error(s"Error processing rpc method $methodName", e)
RpcFunctionFailure(1, e.getMessage, e)
RpcFunctionFailure(1, e.toString, e)
}
} else {
new RpcFunctionFailure(s"Could not find rpcMethodHandler $methodName")
Expand Down
21 changes: 21 additions & 0 deletions vuu/src/main/scala/org/finos/vuu/net/rpc/Rpc.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
package org.finos.vuu.net.rpc

import org.finos.vuu.net.RequestContext
import org.finos.vuu.viewport.ViewPortColumns

object Rpc {
type Function = RpcParams => RpcFunctionResult
type FunctionName = String
}

class RpcParams(
val params: Array[Any],
val namedParams: Map[String, Any],
val viewPortColumns: Option[ViewPortColumns],
val ctx: RequestContext)

trait RpcFunctionResult {}

case class RpcFunctionSuccess(optionalResult: Option[Any]) extends RpcFunctionResult {
def this(result: Any) = this(Some(result))

def this() = this(None)
}

case class RpcFunctionFailure(code: Int, error: String, exception: Exception) extends RpcFunctionResult {
def this(error: String) = this(1, error, null)
}
23 changes: 0 additions & 23 deletions vuu/src/main/scala/org/finos/vuu/net/rpc/RpcMethodHandler.scala

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ class ViewPortContainer(val tableContainer: TableContainer, val providerContaine
treeNodeStatesByVp.get(vpId)
}

def handleRpcRequest(viewPortId: String, rpcName: String, params: Any) (ctx: RequestContext): RpcFunctionResult = {
def handleRpcRequest(viewPortId: String, rpcName: String, params: Map[String, Any]) (ctx: RequestContext): RpcFunctionResult = {
val viewPort = this.getViewPortById(viewPortId)

if(viewPort == null)
throw new Exception(s"No viewport $viewPortId found for RPC Call for $rpcName")

val viewPortDef = viewPort.getStructure.viewPortDef

viewPortDef.service.processRpcRequest(rpcName, new RpcParams(null, null, Some(params), Some(viewPort.getColumns), ctx))
viewPortDef.service.processRpcRequest(rpcName, new RpcParams(null, params, Some(viewPort.getColumns), ctx))
}

def callRpcService(vpId: String, method: String, params: Array[Any], namedParams: Map[String, Any], session: ClientSessionId)(ctx: RequestContext): ViewPortAction = {
Expand All @@ -95,7 +95,7 @@ class ViewPortContainer(val tableContainer: TableContainer, val providerContaine
throw new Exception(s"No viewport $vpId found for RPC Call for $method")

val viewPortDef = viewPort.getStructure.viewPortDef
viewPortDef.service.processViewPortRpcCall(method, new RpcParams(params, namedParams, None, Some(viewPort.getColumns), ctx))
viewPortDef.service.processViewPortRpcCall(method, new RpcParams(params, namedParams, Some(viewPort.getColumns), ctx))
}

def callRpcCell(vpId: String, rpcName: String, session: ClientSessionId, rowKey: String, field: String, singleValue: Object): ViewPortAction = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ class DefaultRpcHandlerTest extends AnyFeatureSpec with Matchers with BeforeAndA
Scenario("Can register and handle Rpc request that perform action") {
handler.registerRpc("myMethod", _ => new RpcFunctionSuccess())

val result = handler.processViewPortRpcCall("myMethod", new RpcParams(Array("param1"), Map("namedParam1" -> "value1"), null, None, ctx))
val result = handler.processViewPortRpcCall("myMethod", new RpcParams(Array("param1"), Map("namedParam1" -> "value1"), None, ctx))

result should be(ViewPortRpcSuccess())
}

Scenario("Can register and handle Rpc request that returns result") {
handler.registerRpc("myMethod", _ => new RpcFunctionSuccess("result"))

val result = handler.processViewPortRpcCall("myMethod", new RpcParams(Array("param1"), Map("namedParam1" -> "value1"), null, None, ctx))
val result = handler.processViewPortRpcCall("myMethod", new RpcParams(Array("param1"), Map("namedParam1" -> "value1"), None, ctx))

result should be(DisplayResultAction("result"))
}
Expand All @@ -44,15 +44,15 @@ class DefaultRpcHandlerTest extends AnyFeatureSpec with Matchers with BeforeAndA
Scenario("Rpc request with null params should return ViewPortRpcSuccess when the rpc method is successful") {
handler.registerRpc("myMethod", _ => new RpcFunctionSuccess())

val result = handler.processViewPortRpcCall("myMethod", new RpcParams(null, null, null, None, ctx))
val result = handler.processViewPortRpcCall("myMethod", new RpcParams(null, null, None, ctx))

result should be(ViewPortRpcSuccess())
}

Scenario("Rpc request should return ViewPortRpcFailure when the rpc method fails") {
handler.registerRpc("myMethod", _ => RpcFunctionFailure(1, "error", new Exception("exception")))

val result = handler.processViewPortRpcCall("myMethod", new RpcParams(null, null, null, None, ctx))
val result = handler.processViewPortRpcCall("myMethod", new RpcParams(null, null, None, ctx))

result should be(ViewPortRpcFailure("Exception occurred calling rpc myMethod"))
}
Expand Down
Loading

0 comments on commit ce4ab99

Please sign in to comment.