I'm trying to develop an app that uses Angular on front and Laravel 5.0 at back.
In HTTP requests, I'm having a hard time getting errors.
This is my MenuController.php that gives my menus to Angular as JSON:
if($control){
$response->data = Menu::get()->toArray();
}
if(!$control) {
$response->error = 'Error!';
}
return json_encode($response);
And this is my menu.service.ts:
private menusUrl = '/api/menu';
constructor (private http: Http) {}
getMenus(): Observable<Menu[]> {
return this.http.get(this.menusUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
private handleError (error: Response | any) {
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
And this is the menu-index.component.ts:
errorMessage: string;
menus: Menu[];
mode = 'Observable';
constructor(private menusService: MenusService) { }
ngOnInit() { this.getMenus(); }
getMenus() {
this.menusService.getMenus()
.subscribe(
menus => this.menus = menus,
error => this.errorMessage = <any>error);
}
The part where I get my menus from Laravel works fine, but I couldn't get the error messages.
Hint: My Angular files are nearly exact copies of the ones that are presented in Angular HTTP Client tutorial. The main problem is how should I return my errors using Laravel so that Angular catches them.
I see a number of things you can improve:
You don't need to manually serialize your data carrier. Laravel handles that for you. All you need to do is return $response.
Your handle error should return the error message. The way chained promises work is that the callback to invoke next receives the return value from the former. So I believe it should be sufficient to return return errMsg.
I do not know if these improvements would resolve your issue, but it is certainly one step in the debugging process.
It turns out that I was not returning a proper error response. Here is the related part in the corrected version of MenuController.php:
if(!$control) {
$response['error'] = 'ERROR!';
return (new Response($response, 400))
->header('Content-Type', 'application/json');
}
Related
I am coding an agent with Dialogflow and a webhook written in PHP. Lately I re-structured parts of my code and now I always get the same error in the "Actions-on-Google-console":
Failed to parse Dialogflow response into AppResponse because of invalid platform response. Could not find a RichResponse or SystemIntent in the platform response for agentId
Now here is part of the code from my webhook:
if($action == "willkommen")
{
$google->Speak("Hallo Welt");
}
$google is an object of a wrapper-PHP-class I created. The code of the method Speak() looks like this:
public function Speak($text,$endConversation=false)
{
if($endConversation)
$expectUserResponse = false;
else
$expectUserResponse = true;
$toGoogle["payload"]["google"]["expectUserResponse"] = $expectUserResponse;
$toGoogle["payload"]["google"]["richResponse"]["items"][0]["simpleResponse"]["textToSpeech"] = $text;
file_put_contents("test.log",json_encode($toGoogle,JSON_PRETTY_PRINT));
echo json_encode($toGoogle,JSON_PRETTY_PRINT);
}
For debugging purpose I write the generated JSON to the file test.log. It contains
{
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Hallo Welt"
}
}
]
}
}
}
}
All the code is executed from start to finish becaue once I edit the string passed over to Speak()
then I can see a change of the JSON-string wirtten to test.log. However I keep getting the error message above. What is wrong with my JSON-string? How can it be Google fails to find the RichResponse?
Thanks a lot!
Any help is appreciated!
Please check your Fallback Intent.
"Actions-on-Google-console" gives this error when fallback intent is not added to the agent.
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've a problem using elasticsearch in a php application. The application is built with zend and uses a .env to hold the following configuration:
ELASTICSEARCH_MAX_DOCUMENTS=250
ELASTICSEARCH_MAX_BULK_SIZE=3M
ELASTICSEARCH_HOST=my-elasticsearch.intern.rz
ELASTICSEARCH_PORT=80
ELASTICSEARCH_USER=user
ELASTICSEARCH_PASSWORD=pw
The call to index the new files is part of a import service class and looks like this:
public function flush(FlushInterface $flushInterface = null) {
$bulk = $this->getSearchDocumentBulk();
if (!empty($bulk->getActions())) {
$response = $bulk->send();
$this->resetSearchDocumentBulk();
if (0 === $response->count()) {
$data = $response->getData();
throw new BulkException(isset($data['message']) ? strip_tags($data['message']) : '');
}
}
$this->documentCache = [];
if ($flushInterface instanceof FlushInterface) {
$flushInterface->flush();
}
return $this;
}
protected function getSearchDocumentBulk() {
if (!($this->searchDocumentBulk instanceof Bulk)) {
$this->searchDocumentBulk = new Bulk($this->getSearchClient()->getClient());
$this->searchDocumentBulk->setIndex(self::INDEX);
}
return $this->searchDocumentBulk;
}
I know it's only a short snippet but it's quite difficult to pull out the relevant code. So please let me know if I have to post some more methods.
The application is started by a symfony command and I'm able to curl to elasticsearch (version 5.1) without any errors.
My problem is that no document is indexed. If I check elasticsearch-head I see that there was no data transfer anymore.
But there's also no error, no exception or something like that. The process is completed with 100% (100,000 of 100,000 files imported). So I've no idea what happens or how to find out the bug.
I've followed the unit testing tutorial and modified it to test a HTTP request to Micro MVC app, based on this post. I can successfully validate the output string, however I'm not sure how to assert the response status code or change the request path.
index.php
<?php
$app = new \Phalcon\Mvc\Micro();
#Default handler for 404
$app->notFound(function () use ($app) {
$app->response->setStatusCode(404, "Not Found")->sendHeaders();
});
$app->post('/api/robots', function() use ($app) {
//Parse JSON as an object
$robot = $app->request->getJsonRawBody();
//Build the response
$app->response->setJsonContent($robot);
return $app->response;
});
$app->get('/', function() {
echo 'Hello';
});
$app->handle();
tests/UnitTest.php
class MvcMicroUnitTest extends \UnitTestCase {
public function testNotFound() {
$path = '/invalid';
$mockRequest = $this->getMock("\\Phalcon\\Http\\Request");
//TODO: Set an invalid URL $path in the mock
$this->di->set('request', $mockRequest, true);
include("../index.php");
//TODO: Assert status is 404
$this->expectOutputString('');
}
public function testPostRobot() {
$rawJson = '{"name":"C-3PO","type":"droid","year":1977}';
$path = '/api/robots';
$mockRequest = $this->getMock("\\Phalcon\\Http\\Request", array(
"getJsonRawBody"));
$mockRequest->expects($this->any())
->method("getRawBody")
->will($this->returnValue($rawJson));
//TODO: Set the $path in the mock
$this->di->set('request', $mockRequest, true);
include("../index.php");
//TODO: Assert status is 200
$this->expectOutputString($rawJson);
}
}
Good news and bad news. Good: as far as you use the standard dispatching principle you will have a response, that would contain the information you need. Small trick – when status is success the header is set to false.
/**
* #param $expected
* #throws ExpectationFailedException
* #return $this
*/
protected function assertResponseCode($expected)
{
$actual = $this->di->getResponse()->getHeaders()->get('Status');
if ($actual !== false && $expected !== 200 && !preg_match(sprintf('/^%s/', $expected), $actual)) {
throw new ExpectationFailedException(sprintf('Failed asserting that response code is "%s".', $expected));
}
$this->assertTrue(true);
return $this;
}
Bad: you are doing it the wrong way. This is area of functional / acceptance testing and there is a fabulous framework called Behat. You should do your own research, but essentially, while PHPUnit is great at testing more or less independent blocks of functionality it sucks at testing bigger things like full request execution. Later you will start experiencing issues with session errors, misconfigured environment, etc., all because each request is supposed to be executed in it's own separate space and you force it into doing the opposite. Behat on the other hand works in a very different way, where for each scenario (post robot, view non-existing page), it sends a fresh request to the server and checks the result. It is mostly used for final testing of everything working together by making assertions on the final result (response object / html / json).
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.