I’m working on a GWT web application that needs to communicate with a common web server. Unfortunately, the server only supports PHP, so I can’t use GWT RPC. That’s why I want to use a simple PHP script on server side, which returns all the necessary data in JSON format. Because I’m fairly new to GWT, my code is based on this example:
http://code.google.com/p/google-web-toolkit-doc-1-5/wiki/GettingStartedJSON
The PHP script seems to work fine. Firebug shows me the returned JSON data and the port 200:
Response:
[{"key1":"k1","value1":"v1"},{"key2":"k2","value2":"v2"},{"key2":"k3","value3":"v3]
However, the response is never processed further. Here is my code:
private static final String JSON_URL = "http://www.myUrl/myScript.php";
public HashMap<String, Integer> loadCalendarTable(String p1, String p2) {
table = new HashMap<String, Integer>();
String url = JSON_URL+"?p1="+p1+"&p2="+p2;
url = URL.encode(url);
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
try {
Request request = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
Window.alert("Couldn't retrieve JSON");
}
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
try {
// parse the response text into JSON
JSONValue jsonValue = JSONParser.parse(response.getText());
JSONArray jsonArray = jsonValue.isArray();
if (jsonArray != null) {
HashMap<String, Integer> hm = updateTable(jsonArray);
}
else
throw new JSONException();
}
catch (JSONException e) {
Window.alert("Could not parse JSON");
}
}
else
Window.alert("Couldn't retrieve JSON (" + response.getStatusText() + ")");
}
});
//(*)
}
catch (RequestException e) {
Window.alert("Couldn't retrieve JSON");
}
return table;
}
private HashMap<String, Integer> updateTable(JSONArray array) {
//do something
return table;}
By executing the application on the web server, there occurs no exception and no alert pops up. By using some alerts (which I omitted in the code above for readability), I noticed that the try-statement in new RequestBuilder() is executed. Another alert at (*) shows, that the try-statement is passed. (No exception occurs, as mentioned before). Obviously, the method onResponseReceived() is never executed. I never called this method, so this could be the reason for my problem. But then, I don’t understand where I should call onResponseReceived().
Remark:
I omitted my PHP script, because that’s actually the same as showed in the online example (http://code.google.com/p/google-web-toolkit-doc-1-5/wiki/GettingStartedJSON). Besides, the script seems to work properly.
How do you know that onResponseRecieved is not being executed? This should be called when your script.php returns JSON data. Assuming your server sends back a 200 status code, the response might be parsed, but no nothing is done with the data
try {
// parse the response text into JSON
JSONValue jsonValue = JSONParser.parse(response.getText());
JSONArray jsonArray = jsonValue.isArray();
if (jsonArray != null) {
HashMap<String, Integer> hm = updateTable(jsonArray);
// Now what? hm isn't actually used for anything...
} else {
throw new JSONException();
}
From the value returned at the end of the method, table is apparently important, but it will be returned, empty before the onResponseRecieved callback is ever invoked. This is because all GWT Ajax calls are asynchronous - the script won't stop running while waiting for the server to resume. Create an alert with response.getTest() in the if (jsonArray != null) block, and you may find that this code is getting called after all. If so, you've fallen victim to That's not async - it is considered generally good JavaScript practice (and all but mandatory in GWT) to wait for results to arrive when ready, and to keep executing as normal in the meantime.
Related
I have a PHP site that calls a REST end point on Salesforce via a visualforce page. When trying to validate the JSON response I confirmed all required fields but am now getting this error:
{"success":false, "message":"System.NullPointerException: Attempt to de-reference a null object
This is coming from the following Apex Class:
public class WebDirectController {
public class ApiException extends Exception {}
public String response {get;set;}
private static final String PRIVATE_APPLICATION_KEY = '123';
public WebDirectController(){}
public Pagereference safeAction(){
Savepoint sp = Database.setSavepoint();
String businessUnit;
try {
Map<String, String> params = ApexPages.currentPage().getParameters();
for (String key : params.keySet()){
system.debug(key +' -> '+ params.get(key));
}
if (params.containsKey('Business_Unit__c') == false){
throw new ApiException('Unauthorized!');
}
businessUnit = params.get('Business_Unit__c');
if (params.containsKey('applicationKey') == false){
throw new ApiException('Unauthorized!');
}
if (params.get('applicationKey') != PRIVATE_APPLICATION_KEY){
throw new ApiException('Unauthorized!');
}
// throws ApiException
validateRequiredFields(params);
WebDirectUtility utility = new WebDirectUtility(businessUnit);
utility.duplicateCheck(params);
if (utility.duplicateAccountList.isEmpty() == false){
// if last opp is needs RX attach attachments to opp and flag opportunity
if (utility.duplicateAccountList.get(0).Opportunities.isEmpty() == false
&& utility.duplicateAccountList.get(0).Opportunities.get(0).Status__c == 'Needs Rx'
&& utility.hasAttachments(params) == true){
// save attachment.
utility.createAttachmentList(params);
utility.addAttachmentParentId(utility.duplicateAccountList.get(0).Opportunities.get(0).Id);
insert utility.attachmentList;
// set status to 'Attention- Call Center'
Opportunity opp = utility.duplicateAccountList.get(0).Opportunities.get(0);
opp.Status__c = 'Attention- Call Center';
update opp;
//utility.sendEmail(params, utility.duplicateAccountList.get(0), opp);
response = '{"success":true}';
return null;
}else{
//utility.sendEmail(params, utility.duplicateAccountList.get(0));
response = '{"success":true}';
return null;
}
}
utility.createAll(params);
insert utility.patientAccount;
utility.addAttachmentParentId(utility.patientAccount.Id);
//system.debug('attachmentList -> '+ utility.attachmentList);
insert utility.attachmentList;
utility.addOpportunityAccountId(utility.patientAccount.Id);
//system.debug('patientOpportunity -> '+ utility.patientOpportunity);
insert utility.patientOpportunity;
utility.addLineItemOpportunityId(utility.patientOpportunity.Id);
//system.debug('lineItemList -> '+ utility.lineItemList);
insert utility.lineItemList;
//send success email to kelly
Opportunity opp = [SELECT Opportunity_Url__c FROM Opportunity WHERE Id =:utility.patientOpportunity.Id];
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setSubject(businessUnit + ' Direct Success Email');
mail.setHtmlBody('<p>'+ businessUnit +' Direct created this opportunity: '+ opp.Opportunity_Url__c +'</p>');
mail.setToAddresses(new String[]{'pedrick#symplmed.com', 'childs#symplmed.com'});
Messaging.sendEmail(new Messaging.Email[] {mail});
response = '{"success":true}';
}catch(Exception e){
ErrorEmail.sendEmail(e);
system.debug(e);
system.debug(e.getMessage());
system.debug(e.getStackTraceString());
response = '{"success":false, "message":"'+ e.getMessage() +'"}';
Database.rollback(sp);
}
return null;
}
public void validateRequiredFields(Map<String, String> params){
Set<String> requiredParams = new Set<String>{'FirstName',
'LastName',
'PersonBirthdate',
'Phone',
'PersonEmail',
'BillingStreet',
'BillingCity',
'BillingState',
'BillingPostalCode'};
for (String rp :requiredParams){
if (params.get(rp) == '' || params.get(rp) == null){
throw new ApiException(rp +' is required!');
}
}
}
}
Not sure what I am missing but I am going on 2 weeks of trying to figure this out.
Thank You
I wanted to close the loop on this. By adding the stack track to the debug msg I was able to locate an error in the setup that resolved the Apex class issue, The product line item entry in the Utility class was pointing to the wrong pricebook.
Adding the Stack Trace to the debug msg was the trick.
Thank you
Login to SF as the user whose credentials you're using in the PHP application. Open the Developer Console (upper right corner, next to your username), execute the call from PHP. Ideally you'll see a debug log generated with more detailed error message, including the line number & stacktrace.
Alternatively - go to Setup -> Debug Logs and enable tracking of that integration user (this will give you files you can view & download; Developer Console has it's quirks, can be bloody slow but at least it'll parse the log for you so it's easier to read, you can set checkpoints in it...)
Hard to say what might be going wrong, you'll have more luck with stacktrace. My wild guess is that utility.duplicateAccountList is null and then if your code executes null.isEmpty() you'll obviously be slapped with an error ;)
P.S. Have you considered exposing your piece of Apex as a proper 'REST service', not a VF page?
https://trailhead.salesforce.com/en/modules/api_basics/units/api_basics_rest
https://trailhead.salesforce.com/en/modules/apex_integration_services/units/apex_integration_webservices
I am trying to communicate to a php server from my gwt project.
I already got a GET request to work, however, my POST request doesn't work so far.
Here's my code:
Button synchronize = new Button("synchronize ",
new ClickHandler() {
public void onClick(ClickEvent event) {
String myurl = URL
.encode("php/test.php");
RequestBuilder builder = new RequestBuilder(
RequestBuilder.POST, myurl);
JSONObject jsonValue = new JSONObject();
jsonValue.put("name", new JSONString("Abc"));
builder.setHeader("Content-Type", "application/json");
try {
Request request = builder.sendRequest(jsonValue.toString(),
new RequestCallback() {
public void onError(Request request,
Throwable exception) {
processResponse("ERROR");
}
public void onResponseReceived(
Request request,
Response response) {
if (200 == response.getStatusCode()) {
processResponse(response
.getText());
} else {
processResponse("ERROR");
}
}
});
} catch (RequestException e) {
processResponse("ERROR");
}
}
});
public void processResponse(String responseString) {
Window.alert(responseString);
}
I can see that the post request goes out and the request payload is a json-object. However, when I try to access the data in the php script, I get the error that the index name is undefined.
Here's the PHP:
<?php
echo $_POST["name"];
?>
Is there something wrong with my PHP?
Does anyone have a working example for this?
While I haven't checked the PHP documentation so far, I tend to remember, that $POST contains the post request's variables, especially useful in a x-www-form-urlencoded request. .. Checked it, yes. I am right :-)
What you actually want is to read the body of the post request and parse it's JSON content to a PHP array or hash.
To read the body see here: How to get body of a POST in php?
$entityBody = file_get_contents('php://input');
Parsing json is described here: Parsing JSON file with PHP
I will not quote the code from there, as it maybe does not exactly fit your needs, but you look for json_decode($json, TRUE).
I am uploading a image file on the server using javascript and servlet. My servlet doPost method is as follows.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println( " Image is sent to server ");
ServletInputStream servletInputStream = request.getInputStream();
File captureFile = new File("./images/img1.jpg");
System.out.println(captureFile.getAbsolutePath());
if(!captureFile.exists()) {
captureFile.createNewFile();
}
FileOutputStream fileOutputStream = new FileOutputStream(captureFile);
int c;
while((c = servletInputStream.read()) != -1) {
fileOutputStream.write((char)c);
//System.out.print((char)c);
}
fileOutputStream.close();
}
In javascript I am creating header and body as follows:
header = 'POST /File/upload HTTP/1.1\r\n';
body += '[[[BINARY_IMAGE]]]\r\n';
body += '\r\r';
Now I want to replace this servlet code with the PHP. But I am not understanding how will I do it in PHP or Python. Can anybody guide me on this? Even Python or Perl replacement will work for me.
I have a url site.com/test.php which has the following code
<?php
$num1 = $_REQUEST['num1'] ;
$num2 = $_REQUEST['num2'] ;
$tot = $num1 + $num2 ;
?>
From an android application using POST/GET num1 and num2 parameters are passed to www.site.com/test.php
How can I make the response in such a way that the android application will be able to get the response from this request.
I tried this
header('Content-Type: application/json');
echo json_encode($response);
but all it does is echo it in the web view and im not able to get the response.Is there someway I can get the response as standard json response,which is not displayed but get it as soon as I hit the url as a response ?
** UPDATE **
#Override
public boolean shouldOverrideUrlLoading (WebView view, String url) {
if(flag) {
URL aURL = new URL(url);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
// read inputstream to get the json..
...
...
return true;
}
return false
}
#override
public void onPageFinished (WebView view, String url) {
if (url contains "form.html") {
flag = true;
}
}
this is the java code I got from SO , which Im planning to use in the android appication
Seems to be a problem in the handling of the response, not the generation of the JSON. Are you clicking a link to the JSON on a page that is has "form.html" in it? Because that is what seems to be assumed in the code you posted.
It seems to be better to just overload the shouldOverrideUrlLoading and check if the url matches your json page. Something like this:
#Override
public boolean shouldOverrideUrlLoading (WebView view, String url) {
if(url.toLowerCase().contains("www.site.com/test.php")) {
URL aURL = new URL(url);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
// read inputstream to get the json..
...
...
return true;
}
return false;
}
It might be a good idea to start an activity and load the JSON in that activity using, for example, an AsyncTask (network operations aren't allowed on the UI thread in the latest android APIs), instead of doing URL.openConnection immediately.
I have one problem..
I am making post request to php script. And I am getting back result as an xml. How can I make my qprogressbar working.
I have tried this:
v
oid MainWindow::init()
{
url = "http://127.0.0.1:8888/direkt_php_qt.php";
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(updateDataTransferProgress(qint64,qint64)));
connect(manager, SIGNAL(finished(QNetworkReply*)),this, SLOT(replyFinished(QNetworkReply*)));
}
void MainWindow::updateDataTransferProgress(qint64 bytesReceived, qint64 bytesTotal)
{
ui->progressBar->setMaximum(bytesTotal + (bytesTotal * 0.25));
ui->progressBar->setValue(bytesReceived);
ui->progressBar->show();
}
But it's not working. I am getting error:
Object::connect: No such signal QNetworkAccessManager::downloadProgress(qint64,qint64)
How can I make this work with manager variable or something like that.
EDIT 2:
This is for example function that is calling init()
void MainWindow::Citanje_korisnika()
{
init();
QUrl params;
params.addQueryItem("action","Citanje_korisnika");
QByteArray data;
data.append(params.toString());
data.remove(0,1);
QNetworkRequest request;
request.setUrl(url);
request.setHeader(QNetworkRequest::ContentTypeHeader,
QVariant("application/x-www-form-urlencoded"));
reply = manager->post(request, data);
}
I tried your code but I always get unexpectedly out from program. Can you change me my function from which I am calling post method so it can work with init()
donwloadProgress is a signal of QNetworkReply.
Try something like this:
url = "http://127.0.0.1:8888/direkt_php_qt.php";
manager = new QNetworkAccessManager(this);
QNetworkReply* reply = manager->get(QNetworkRequest(url));
connect(reply, SIGNAL(downloadProgress(qint64, qint64)),this, SLOT(updateDataTransferProgress(qint64,qint64)));