MobileFirst 7.0 image upload and javascript adapter parameters size limit - ibm-mobilefirst

It seems that there is already a similar question on so and we meet with it indeed.
We are calling adapters and sending encoded base64 strings to the backend. All things works fine with tiny pictures less than 1Mb. But if the image size is larger (eg. 4Mb, just a ordinary Photo from the end-user's iPhone album), it stucked with adapter invoking errors. I also find clues after debugging that, in condition with uploading large image the adapter will never step into the backend business logic but in the condition the tiny pics can.
Some of the code snippets could be like below:
var base64Str = "";
var reader = new FileReader();
reader.onload = function(e) {
base64Str = e.target.result;
preview.setAttribute('src', base64Str );
uploadImage(picUuid, base64Str);
}
//calling the HTTP image upload adapter
function uploadImage(uuid, base64Data){
WL.Logger.debug("base64Data:" + base64Data);
var invocationData = {
adapter : 'ImageUploadAdapter',
procedure : 'uploadImage',
parameters : [uuid, base64Data]
};
WL.Client.invokeProcedure(invocationData, {
onSuccess : uploadImageSuccess,
onFailure : uploadImageFailure,
});
}

function encodeImageFileAsURL() {
var filesSelected = document.getElementById("inputFileToLoad").files;
if (filesSelected.length > 0) {
var fileToLoad = filesSelected[0];
var fileReader = new FileReader();
fileReader.onload = function(fileLoadedEvent) {
var srcData = fileLoadedEvent.target.result; // <--- data: base64
var newImage = document.createElement('img');
newImage.src = srcData;
alert(srcData);
document.getElementById("imgTest").innerHTML = newImage.outerHTML;
alert("Converted Base64 version is " + document.getElementById("imgTest").innerHTML);
console.log("Converted Base64 version is " + document.getElementById("imgTest").innerHTML);
uploadImage(srcData);
}
fileReader.readAsDataURL(fileToLoad);
}
}
//calling the HTTP image upload adapter
function uploadImage(srcData){
WL.Logger.debug("srcData:" + srcData);
var invocationData = {
adapter : 'ImageUploadAdapter',
procedure : 'uploadImage',
parameters : [srcData]
};
WL.Client.invokeProcedure(invocationData, {
onSuccess : uploadImageSuccess,
onFailure : uploadImageFailure,
});
}

MobileFirst Platform 7.0 introduced Java adapters in addition to the existing JavaScript adapters.
With Java adapters there is no such limitation for the file sizes that can be operated on when using JavaScript adapters and data can be handled as Binary rather than encoded to base64, etc.
In other words, there is no multi-part support in JavaScript adapters, whereas in Java adapters (that are based on the JAX-RS specifications) you can.
You can read more about it here:
https://developer.ibm.com/mobilefirstplatform/documentation/getting-started-7-0/server-side-development/adapter-framework-overview/

Related

Dialogflow .NET core, C# - detect intent not working

I want to invoke DetectIntent programatically.
I am using Google.Cloud.Dialogflow.V2 - Client libraries.
using Google.Cloud.Dialogflow.V2;
var query = new QueryInput
{
Text = new TextInput
{
Text = text,
LanguageCode = "en-us"
}
};
var sessionId = "1234567890";
var agent = "myAgentName";
var creds = GoogleCredential.FromFile("JSONFileName");
Channel channel = new Channel(
SessionsClient.DefaultEndpoint.Host, SessionsClient.DefaultEndpoint.Port, creds.ToChannelCredentials());
var client = SessionsClient.Create(channel);
DetectIntentRequest request = new DetectIntentRequest
{
SessionAsSessionName = new SessionName("smartresort-facebook-bot-fgvjh", "1111"),
QueryInput = query,
};
DetectIntentResponse response = client.DetectIntent(request);
With above code I am getting error as below
I am already using same JSON file in node js code and it is working fine. So in nodejs detect intent code is working fine. I am trying to do the same in .NET core.
After this I have tried another code snippet.
var client = SessionsClient.Create();
var response = client.DetectIntent(
session: new SessionName("smartresort-facebook-bot-fgvjh", "1234567890"),
queryInput: new QueryInput()
{
Text = new TextInput()
{
Text = text,
LanguageCode = "en-us"
}
}
);
I am not trying to write fulfillment which would be called after the intent is detected. I am trying to write the code before intent is detected. So I want to give a call to detect intent and then process the response based on which intent is detected.
Check my answer here, It is an example on how to integrate Dialogflow with .Net Core based on a working sample. If you still have more questions let me know and I will be happy to help!

IBM Worklight - Could not invoke the SQL adapter procedure for the insert query from the client side . What's wrong with my coding?

I'm getting a blank screen while running the code in the webpage. The adapter procedure alone is getting invoked correctly but I couldn't invoke it from my client side.I'm using Db2 database. Please help.
Here is my JavaScript code..
function loadDetails(x,y,z,a,b,c,d,e,f,g,h,i){
var x= document.getElementById("firstname").value;
var y= document.getElementById("lastname").value;
var z= document.getElementById("doorno").value;
var a= document.getElementById("streetname").value;
var b= document.getElementById("area").value;
var c= document.getElementById("zipcode").value;
var d= document.getElementById("landmark").value;
var e= document.getElementById("secques").value;
var f= document.getElementById("secans").value;
var g= document.getElementById("emailaddress").value;
var h= document.getElementById("username").value;
var i= document.getElementById("password").value;
var invocationData = {
adapter : 'DBAdapter',
procedure : 'addDBAdapter',
parameters : [x,y,z,a,b,c,d,e,f,g,h,i]
};
WL.Client.invokeProcedure(invocationData,{
onSuccess : loadDetailsSuccess,
onFailure : loadDetailsFailure
});
}
function loadDetailsSuccess(){
alert("Registration Successfull. Please login to continue...");
window.location.href = 'login.html';
}
function loadDetailsFailure(){
WL.Logger.error("load data failure");
}
DBAdapter-impl.js
var addStatement = WL.Server.createSQLStatement("insert into CUSTOMER(FIRSTNAME,LASTNAME,DOORNO,AREA,STREETNAME,ZIPCODE,LANDMARK,SECQUES,SECANS,EMAILADDRESS,USERNAME,PASSWORD) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)");
function addDBAdapter(x,y,z,a,b,c,d,e,f,g,h,i) {
return WL.Server.invokeSQLStatement({
preparedStatement : addStatement,
parameters : [x,y,z,a,b,c,d,e,f,g,h,i]
});
}
As eabe rightly so mention in the comments, and we've all missed it(!), Worklight is a Single Page Application and indeed window.location.href = 'login.html'; seems to be the culprit here.
See this related question on this subject matter that also contain solutions:
How to change between pages using Jquery Mobile in Worklight
Basically, you can use either jQuery's .load or jQuery Mobile's .changePage (or the equivalent of other libraries to do the same) in order to load the contents of another page, or "switch" to another. Doing what you do, you lost the Worklight "context" and nothing will work or display.
Also review this training material:
Building a multipage application

Display result from server in IBM Worklight

I have implemented HTTP adapter in IBM Worklight. I want to display the result returned from server. I want to display HTML file. My code is
function getFeeds() {
var input = {
method : 'get',
returnedContentType : 'text',
path : "marketing/partners.html"
};
WL.Logger.debug("sdfsds");
return WL.Server.invokeHttp(input);
}
I want to receive(display) WL.Server.invokeHttp(input). After receiving it I want to parse the data.
Take a look at the Server-side Development Getting Started Modules. Inside the HTTP adapter – Communicating with HTTP back-end systems Module on Slide 15 - 'XSL Transformation Filtering' will show you how to filter data you get back from the backend. Further parsing and showing data has to be done on the client using onSuccess callback for WL.Client.invokeProcedure. There's a module for that too.
Here's an example of getting data and showing to a user:
var invocationData = {
adapter : 'adapter-name',
procedure : 'procedure-name',
parameters : []
};
var options = {};
options.onSuccess = function (response) {
//response is a JavaScript object
$("#id").html(response.invocationResponse.text);
}
options.onFailure = function (response) {
alert('Failed!'); //You probably want something more meaningful here.
}
WL.Client invokeProcedure(invocationData, options);
There are JavaScript libraries you can add to make searching for values inside the JSON response easier, such as: jspath and jquery-jspath. There's also XPath if you're working with XML.
If you retrieve it as plain text, once you got it back to your application, do something like
$("#container-id").html(response.invocationResponse.text);
This will inject the HTML you've retrieved to an element with id container-id.

log4javascript - obtain history of messages programmatically?

I'm looking into using a javascript logging framework in my app.
I quite like the look of log4javascript (http://log4javascript.org/) but I have one requirement which I'm not sure that it satisfies.
I need to be able to ask the framework for all messages which have been logged.
Perhaps I could use an invisible InPageAppender (http://log4javascript.org/docs/manual.html#appenders) to log to a DOM element, then scrape out the messages from that DOM element - but that seems pretty heavy.
Perhaps I need to write my own "InMemoryAppender"?
There's an ArrayAppender used in log4javascript's unit tests that stores all log messages it receives in an array accessible via its logMessages property. Hopefully it should show up in the main distribution in the next version. Here's a standalone implementation:
var ArrayAppender = function(layout) {
if (layout) {
this.setLayout(layout);
}
this.logMessages = [];
};
ArrayAppender.prototype = new log4javascript.Appender();
ArrayAppender.prototype.layout = new log4javascript.NullLayout();
ArrayAppender.prototype.append = function(loggingEvent) {
var formattedMessage = this.getLayout().format(loggingEvent);
if (this.getLayout().ignoresThrowable()) {
formattedMessage += loggingEvent.getThrowableStrRep();
}
this.logMessages.push(formattedMessage);
};
ArrayAppender.prototype.toString = function() {
return "[ArrayAppender]";
};
Example use:
var log = log4javascript.getLogger("main");
var appender = new ArrayAppender();
log.addAppender(appender);
log.debug("A message");
alert(appender.logMessages);

File Upload Control in Domino

I need to post a file to Domino Server from a PhoneGap Application.
Here is the PhoneGap File Transfer example
// !! Assumes variable fileURI contains a valid URI to a text file on the device
var win = function(r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
}
var fail = function(error) {
alert("An error has occurred: Code = " = error.code);
}
var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=fileURI.substr(fileURI.lastIndexOf('/')+1);
options.mimeType="text/plain";
var params = new Object();
params.value1 = "test";
params.value2 = "param";
options.params = params;
var ft = new FileTransfer();
ft.upload(fileURI, "http://some.server.com/upload.php", win, fail, options);
//This is a PHP example - Domino would be like
// ft.upload(fileURI, "http://some.server.com/database.nsf/attachmentForm? createDocument", win, fail, options);
Does anyone know what needs to be done in Domino to get the file attachment that is being posted?
The easiest thing to do would be to create a form in Domino containing a File Upload control. You should be able to open the Domino form with a browser and see the generated html form that would normally be used. In there you will find all the info you need. This is of course dependent on the ft.upload method acting like an http multipart/form-data POST.