I've been doing a lot of playing lately with MobileFirst, and one of the cooler features it has is the ability to write adapters in JavaScript. I blogged about this last week and today I thought I'd share a few tips/notes for folks who may be new to this feature.
First and foremost, it is important to remember that you are not using a full Node.js-style stack. You are working with a subset of the Rhino container developed by Mozilla. This is a JavaScript engine that runs within the context of a Java server. However, this is not a full Rhino implementation as some features, like load(), are not implemented. Unfortunately we don't document these differences (yet - I'm filing an enhancement request for this today).
Second, you cannot debug via console.log. Instead, simply use the WL.Logger API as shown below:
function getDetail(id) {
WL.Logger.info("getDetail, requesting id "+id);
return WL.Server.invokeSQLStatement({
preparedStatement : getDetailStmt,
parameters:[id]
});
}
And where do those logs show up? Type mfp logs
at the command line to be shown where your logs exist:
Then you can simply go to that directory and look at messages.log. I'd simply tail -f
it while you work to see incoming messages. The log is a bit verbose, but you could use other tools to filter it out.
The third point to consider is that adapters are session-based. That means you can persist data by simply using a global JavaScript variable, but it will not be global to the server.
Finally, and I've mentioned these before, but don't forget that you need to "build/deploy" when you edit your adapter files. You can use the bd shortcut for adapters just like you do for your web assets: mfp bd
. You can also test your adapters directly from the command line using mfp invoke
.
Archived Comments
Raymond Camden Another great post on these series.
Here are some tips:
1. You can use "mfp run" to start the mfp dev server and see the logs instead of using mfp logs and using tail.
Just that mfp run will not termite it will be there printing logs statements, when you Ctrl+C it kills the server.
The use case is useful when you have two terminals open one you can do mfp bd in the adapters/ folder and then other you can run mfp run to see the logs
2. You can also use the new command in MFP 7.0 to call adapters mfp adapter call, it supports Java and JavaScript adapters, we eventually deprecate the mfp invoke on the CLI
3. You can can use the new Client API to call adapters instead of using WL.Client.invokeProcedure you can use new MFP 7.0 WLResourceRequest.send it uses REST HTTP giving providing the ability to cache the adapter responses and more power to control the request with things like http headers.
Keep the good work !
What is "better" - mfp invoke or mfp adapter call?
The adapter call command is more capable, and thus better. It supports the basic REST verbs, and is the only way to test the new Java Adapter (REST only). We want to encourage developers to move over to proper REST calls for the JS-based adapters too.
The original Rhino-based JS adapters were RPC based, but the actual implementation was always implemented using POST for the API and Studio tester. The CLI's "invoke" command actually uses GETs, and could fail under large payloads. As Carlos mentioned, we'll soon deprecate, then remove support for the legacy "invoke" command, as the "call" command supports all adapters.
One other point to share -- The "build" and "bd" shortcut are context aware. Which means that if you are working on a single adapter, run the command from that adapters directory, and it will be the only artifact processed, which will greatly improve the build and deploy time. The same is true for individual apps. Conversely, being at the "/adapters", "/apps", or project root, will process all child assets.
Query - is there a REST API for using MFP from your app? In the docs they show a REST API, but it is just (from what I can tell) to work with MFP in general. For example, list or add adapters. I don't see a REST API to *use* adapters. Now, maybe the JS API uses REST behind the scenes, but that's not what I mean. Is there a *documented* way for me to use an adapter in a hybrid app, or anywhere really, via REST?