thrift nodejs client and php server works together? - php

I plan to use nodejs as the client, and php as the server. I use the official tutorial.thrift.
I set up a nginx server to host the localhost:9099 with the dir /path/to/my/tutorial/, generate a server script as index.php and place it in the root ,when visit the localhost:9099,so that client visit the server through index.php.
the index.php content:
<?php
error_reporting(E_ALL);
require_once __DIR__ . "/Thrift/ClassLoader/ThriftClassLoader.php";
use Thrift\ClassLoader\ThriftClassLoader;
$ROOT = realpath(dirname(__FILE__));
$GEN_DIR = $ROOT.'/gen-php';
$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', $ROOT);
$loader->registerNamespace('Swoole', $ROOT);
$loader->registerNamespace('tutorial', $GEN_DIR);
$loader->registerDefinition('shared', $GEN_DIR);
$loader->registerDefinition('tutorial', $GEN_DIR);
$loader->register();
if (php_sapi_name() == 'cli') {
ini_set("display_errors", "stderr");
}
use Thrift\Protocol\TBinaryProtocol;
use Thrift\Transport\TPhpStream;
use Thrift\Transport\TBufferedTransport;
use Thrift\Server\TServer;
header('Content-Type', 'application/x-thrift');
if (php_sapi_name() == 'cli') {
echo "\r\n";
}
$handler = new \tutorial\Handler();
$processor = new \tutorial\CalculatorProcessor($handler);
$transport = new TBufferedTransport(new TPhpStream(TPhpStream::MODE_R | TPhpStream::MODE_W));
$protocol = new TBinaryProtocol($transport, true, true);
$transport->open();
$processor->process($protocol, $protocol);
$transport->close();
the client.node.js content:
/**
* Created by Kron on 16/4/12.
*/
var thrift = require('thrift');
var ThriftTransports = require('thrift/transport');
var ThriftProtocols = require('thrift/protocol');
var Calculator = require('../gen-nodejs/Calculator');
var ttypes = require('../gen-nodejs/tutorial_types');
transport = ThriftTransports.TBufferedTransport();
protocol = ThriftProtocols.TBinaryProtocol();
var connection = thrift.createConnection("localhost", 9099, {
transport : transport,
protocol : protocol
});
var client = thrift.createClient(Calculator, connection);
connection.on('error', function(err) {
console.log(err);
//assert(false, err);
});
// Create a Calculator client with the connection
client.ping(function(err, response) {
console.log('ping()');
});
client.add(1,1, function(err, response) {
console.log("1+1=" + response);
});
work = new ttypes.Work();
work.op = ttypes.Operation.DIVIDE;
work.num1 = 1;
work.num2 = 0;
client.calculate(1, work, function(err, message) {
if (err) {
console.log("InvalidOperation " + err);
} else {
console.log('Whoa? You know how to divide by zero?');
}
});
work.op = ttypes.Operation.SUBTRACT;
work.num1 = 15;
work.num2 = 10;
client.calculate(1, work, function(err, message) {
console.log('15-10=' + message);
client.getStruct(1, function(err, message){
console.log('Check log: ' + message.value);
//close the connection once we're done
connection.end();
});
});
The client.php content:
<?php
error_reporting(E_ALL);
require_once __DIR__ . "/../Thrift/ClassLoader/ThriftClassLoader.php";
use Thrift\ClassLoader\ThriftClassLoader;
$ROOT = realpath(dirname(__FILE__).'/../');
$GEN_DIR = $ROOT.'/gen-php';
$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', $ROOT);
$loader->registerNamespace('Swoole', $ROOT);
$loader->registerNamespace('tutorial', $GEN_DIR);
$loader->registerDefinition('shared', $GEN_DIR);
$loader->registerDefinition('tutorial', $GEN_DIR);
$loader->register();
use Thrift\Protocol\TBinaryProtocol;
use Thrift\Transport\TSocket;
use Thrift\Transport\THttpClient;
use Thrift\Transport\TBufferedTransport;
use Thrift\Exception\TException;
try {
if (array_search('--http', $argv)) {
$socket = new THttpClient('localhost', 9099, '/clients_servers/tutorial.server.php');
} else {
$socket = new THttpClient('localhost', 9099); // 8080 for node server, 9099 for php server
}
$transport = new TBufferedTransport($socket, 1024, 1024);
$protocol = new TBinaryProtocol($transport);
$client = new \tutorial\CalculatorClient($protocol);
$transport->open();
$client->ping();
print "ping()\n";
$sum = $client->add(1,1);
print "1+1=$sum\n";
$work = new \tutorial\Work();
$work->op = \tutorial\Operation::DIVIDE;
$work->num1 = 1;
$work->num2 = 0;
try {
$client->calculate(1, $work);
print "Whoa! We can divide by zero?\n";
} catch (\tutorial\InvalidOperation $io) {
print "InvalidOperation: $io->why\n";
}
$work->op = \tutorial\Operation::SUBTRACT;
$work->num1 = 15;
$work->num2 = 10;
$diff = $client->calculate(1, $work);
print "15-10=$diff\n";
$log = $client->getStruct(1);
print "Log: $log->value\n";
$transport->close();
} catch (TException $tx) {
print 'TException: '.$tx->getMessage()."\n";
}
They're almost the same as original.
when I use client.php visit the host, It works well.
when I use client.node.js visit the host, It doesn't work.
when I try to use a node server,not the host, visit it use the client.php,I have to change $socket = new THttpClient('localhost', 9099) to $socket = new TSocket('localhost', 9099) to make it work.
client.node.js never ever touched the localhost:9099, and without any stdout.

Finally my partner helped me found the answer.
the official demo of nodejs cient has some problems:
official code:
transport = ThriftTransports.TFramedTransport();
protocol = ThriftProtocols.TBinaryProtocol();
our code:
transport = ThriftTransports.TFramedTransport;
protocol = ThriftProtocols.TBinaryProtocol;
remove the (), that makes the code work.

[hbase-dir]/bin/hbase-daemon.sh start thrift -f
I am facing same error. Refer http://dailyjs.com/post/hbase
TFramedTransport is disable by default. You have to enable it by using above command.
Note : After enable you can't able to connect php. I AM using different protocols for that in php
Check this :
NodeJS Hbase thrift weirdness

Related

Softlayer API PHP error Function ("setObjectFilter") is not a valid method for this service

I tried to use object filter to get valid device:
Below is the php code:
$client= SoftLayer_SoapClient::getClient('SoftLayer_Account', null, $username, $apiKey);
$filter = new stdClass();
$filter->applicationDeliveryControllers = new stdClass();
$filter->applicationDeliveryControllers->billingItem = new stdClass();
$filter->applicationDeliveryControllers->billingItem->id = new stdClass();
$filter->applicationDeliveryControllers->billingItem->id->operation = new stdClass();
$filter->applicationDeliveryControllers->billingItem->id->operation = $bId;
$client->setObjectFilter($filter);
try {
$mask ='mask[id, name]';
$client->setObjectMask($mask);
$myInstance = $clientNetscaler->getApplicationDeliveryControllers();
} catch(exception $ex) {
}
I got the following error in my run time environment:
There was an error querying the SoftLayer API: Function
("setObjectFilter") is not a valid method for this service
The error came from line $client->setObjectFilter($filter);
Anybody has any idea of why there's such error?
For me the filter is working fine. Just in case, I copied my code. Please make sure you have PHP 5.2.3 or higher and the PHP extension for SOAP. Also try re-downloading the Softlayer PHP client https://github.com/softlayer/softlayer-api-php-client and try again.
Regards
<?php
require_once ('/SoapClient.class.php');
$apiUsername = 'set me';
$apiKey = 'set me';
$accountService = Softlayer_SoapClient::getClient('SoftLayer_Account', null,$apiUsername, $apiKey);
$bId = 51774239;
$filter = new stdClass();
$filter->applicationDeliveryControllers = new stdClass();
$filter->applicationDeliveryControllers->billingItem = new stdClass();
$filter->applicationDeliveryControllers->billingItem->id = new stdClass();
$filter->applicationDeliveryControllers->billingItem->id->operation = new stdClass();
$filter->applicationDeliveryControllers->billingItem->id->operation = $bId;
$accountService->setObjectFilter($filter);
$mask ='mask[id, name]';
$accountService->setObjectMask($mask);
try {
$myInstance = $accountService->getApplicationDeliveryControllers();
print_r($myInstance);
} catch (Exception $e) {
die('Unable to executre the request. ' . $e->getMessage());
}

Salesforce error: Element {}item invalid at this location

i am using the below code to connect to salesforce using php
require_once ('SforcePartnerClient.php');
require_once ('SforceHeaderOptions.php');
require_once ('SforceMetadataClient.php');
$mySforceConnection = new SforcePartnerClient();
$mySforceConnection->createConnection("cniRegistration.wsdl");
$loginResult = $mySforceConnection->login("username", "password.token");
$queryOptions = new QueryOptions(200);
try {
$sObject = new stdclass();
$sObject->Name = 'Smith';
$sObject->Phone = '510-555-5555';
$sObject->fieldsToNull = NULL;
echo "**** Creating the following:\r\n";
$createResponse = $mySforceConnection->create($sObject, 'Account');
$ids = array();
foreach ($createResponse as $createResult) {
print_r($createResult);
array_push($ids, $createResult->id);
}
} catch (Exception $e) {
echo $e->faultstring;
}
But the above code is connect to salesforce database.
But is not executing the create commands. it's giving me the below error message
Creating the following: Element {}item invalid at this location
can any one suggest me to overcome the above problem
MAK, in your sample code SessionHeader and Endpoint setup calls are missing
$mySforceConnection->setEndpoint($location);
$mySforceConnection->setSessionHeader($sessionId);
after setting up those, if you still see an issue, check the namespace urn
$mySforceConnection->getNamespace
It should match targetNamespace value in your wsdl
the value of $mySforceConnection should point to the xml file of the partner.wsdl.xml.
E.g $SoapClient = $sfdc->createConnection("soapclient/partner.wsdl.xml");
Try adding the snippet code below to reference the WSDL.
$sfdc = new SforcePartnerClient();
// create a connection using the partner wsdl
$SoapClient = $sfdc->createConnection("soapclient/partner.wsdl.xml");
$loginResult = false;
try {
// log in with username, password and security token if required
$loginResult = $sfdc->login($sfdcUsername, $sfdcPassword.$sfdcToken);
}
catch (Exception $e) {
global $errors;
$errors = $e->faultstring;
echo "Fatal Login Error <b>" . $errors . "</b>";
die;
}
// setup the SOAP client modify the headers
$parsedURL = parse_url($sfdc->getLocation());
define ("_SFDC_SERVER_", substr($parsedURL['host'],0,strpos($parsedURL['host'], '.')));
define ("_SALESFORCE_URL_", "https://test.salesforce.com");
define ("_WS_NAME_", "WebService_WDSL_Name_Here");
define ("_WS_WSDL_", "soapclient/" . _WS_NAME_ . ".wsdl");
define ("_WS_ENDPOINT_", 'https://' . _SFDC_SERVER_ . '.salesforce.com/services/wsdl/class/' . _WS_NAME_);
define ("_WS_NAMESPACE_", 'http://soap.sforce.com/schemas/class/' . _WS_NAME_);
$urlLink = '';
try {
$client = new SoapClient(_WS_WSDL_);
$sforce_header = new SoapHeader(_WS_NAMESPACE_, "SessionHeader", array("sessionId" => $sfdc->getSessionId()));
$client->__setSoapHeaders(array($sforce_header));
} catch ( Exception $e ) {
die( 'Error<br/>' . $e->__toString() );
}
Please check the link on Tech Thought for more details on the error.

PHP REST API got error when try to add New Users to Jasperserver

I got some problem with php-sample.
I want to add users, but there were something went wrong.
Please help me!!
Here is code that I used:
<!DOCTYPE html>
<?php
require_once "vendor/autoload.php";
require_once "autoload.dist.php";
require_once "client/JasperClient.php";
require_once "client/User.php";
require_once "client/Role.php";
$client = new Jasper\JasperClient(
"localhost", // Hostname
8080, // Port
"jasperadmin", // Username
"jasperadmin", // Password
"/jasperserver-pro", // Base URL
"organization_1"
); // Organization (pro only)
$newUser = new Jasper\User("BI_User", // username
"superSTRENGTHpassw0rd", // password
"clever#email.com", // email
"Business Intelligence User", // description
"organization_1", // parent organization
"true" // enabled
);
$role = new Jasper\Role("ROLE_USER", NULL, "false");
$newUser->addRole($role);
try {
$client->putUsers($newUser);
}
catch (Exception $e) {
printf("Could not add new user: %s", $e->getMessage());
}?>
And Here is the error message that I got:
Could not add new user: Unexpected HTTP code returned: 400 Body of response:
Apache Tomcat/6.0.26 - Error report HTTP Status 400 - type Status
reportmessage description The request sent by the client was syntactically
incorrect ().Apache Tomcat/6.0.26
Ask I spent time google so much on that problem, I have found the solution.
Here is my solution whether someone are interested.
<?php
require_once "vendor/autoload.php";
require_once "autoload.dist.php";
use Jaspersoft\Client\Client;
use Jaspersoft\Dto\User\User;
use Jaspersoft\Dto\Role\Role;
function registerUsers(){
$client = new Client(
"localhost",
"8080",
"superuser",
"superuser",
"/jasperserver-pro",
"null"
);
$file_path = 'data/userlist.csv';
$handle = fopen($file_path,'r');
$array_users = array();
$i=0;
while (!feof($handle) !==false){
$line = fgetcsv($handle,1024,',');
$i++;
if($i==1) continue;
if(!empty($line)){
for($c = 0; $c < count($line); $c++){
$username = $line[0];
$password = $line[1];
$email = $line[2];
$fullname = $line[3];
$tenantId = $line[4];
$enabled = $line[5];
$user = new User($username, $password, $email,
$fullname, $tenantId, $enabled);
$role = new Role('ROLE_USER', null, 'false');
$array_users[$c] = $user;
$array_users[$c]->addRole($role);
try {
$client->userService()->addUsers($array_users[$c]);
} catch (Exception $e) {
printf('Could not add new user: %s', $e->getMessage());
}
}
}
}
}?>
And here is my csv data file:
User Name,Password,Email Address,Full Name,Tenant ID,Enable
User1,superSTRENGTHpassw0rd,clever#email.com,User One,a,true
User2,superSTRENGTHpassw0rd,clever#email.com,User One,a,true
User3,superSTRENGTHpassw0rd,clever#email.com,User One,a,true
User6,superSTRENGTHpassw0rd,clever#email.com,User One,organization_1,true
User7,superSTRENGTHpassw0rd,clever#email.com,User One,organization_1,true
User8,superSTRENGTHpassw0rd,clever#email.com,User One,b,true
User9,superSTRENGTHpassw0rd,clever#email.com,User One,b,true
User10,superSTRENGTHpassw0rd,clever#email.com,User One,c,true
User11,superSTRENGTHpassw0rd,clever#email.com,User One,c,true

PHP - Thrift 0.9.0 - Class 'Thrift\Transport\TTransport' not found in TSocket.php

Trying out using PHP with thrift and I can't run it properly due to being unable to find certain classes. I was able to do this in 0.8.0 fine, now that I've downloaded 0.9.0 I'm at a loss as to how I should include the thrift files properly.
Here is my snippet of code:
$GLOBALS['THRIFT_ROOT'] = '/home/user/final/Thrift';
require_once( $GLOBALS['THRIFT_ROOT'] . '/Transport/TSocket.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/Transport/TBufferedTransport.php' );
require_once( $GLOBALS['THRIFT_ROOT'] . '/Protocol/TBinaryProtocol.php' );
require_once( 'Hbase/Hbase.php');
require_once( 'Hbase/Types.php');
use Hbase\HbaseClient;
try
{
$socket = new TSocket('127.0.0.1', 9090);
$transport = new TBufferedTransport($socket, 1024, 1024);
$protocol = new TBinaryProtocolAccelerated($transport);
$client = new HbaseClient( $protocol );
$transport->open();
//show all tables
$tables = $client->getTableNames();
foreach ( $tables as $name )
{
echo( " found: {$name}\n" );
}
}
catch (Exception $e)
{
echo "Exception: %e\r\n";
}
All files are layed out properly in the directories as seen here:
But when I run the file from the command line (php -f index.php) I'm receiving this error:
Class 'Thrift\Transport\TTransport' not found in
/home/user/final/Thrift/Transport/TSocket.php on line 35
I'm really at a loss as to what I should do next, I'm not familiar with using the "use" command or "namespace" in PHP, which I have a feeling would help solve this. The thrift README for php also mentions using symfony, which is just further confusing me.
Any advice would be greatly appreciated!
Thanks!
Name space Like this:
use Thrift\Transport\TSocket;
use Thrift\Transport\TBufferedTransport;
use Thrift\Protocol\TBinaryProtocolAccelerated;
try {
$socket = new TSocket('xxxxx', 9090);
$transport = new TBufferedTransport($socket, 1024, 1024);
$protocol = new TBinaryProtocolAccelerated($transport);
$client = new HbaseClient($protocol);
$transport -> open();
//show all tables
$tables = $client -> getTableNames();
foreach ($tables as $name) {
echo(" found: {$name}\n");
}
} catch (Exception $e) {
print_r($e);
}
Use ClassLoader. Hbase classes do not support classLoader but uses Thrift namespaces.
<?php
define('THRIFT_PATH', __DIR__);
require_once THRIFT_PATH . '/Thrift/ClassLoader/ThriftClassLoader.php';
$classLoader = new Thrift\ClassLoader\ThriftClassLoader();
$classLoader->registerNamespace('Thrift', THRIFT_PATH);
$classLoader->register();
// (!) include after classLoader
require_once 'Hbase/Hbase.php';
require_once 'Hbase/Types.php';
try
{
$socket = new Thrift\Transport\TSocket('127.0.0.1', 9090);
$transport = new Thrift\Transport\TBufferedTransport($socket, 1024, 1024);
$protocol = new Thrift\Protocol\TBinaryProtocolAccelerated($transport);
$client = new Hbase\HbaseClient($protocol);
$transport->open();
//show all tables
$tables = $client->getTableNames();
foreach ($tables as $name)
{
echo "found: {$name}\n";
}
}
catch (Exception $e)
{
echo "Exception: %e\r\n";
}
P.S. This code work for your directory structure:
you need to keep Thrift parent dirname, don't rename it;
the directory structure like this
Thrift/Base
Thrift/ClassLoader
Thrfit/xxxx
example
I put whole Thrift folder in htdocs\thrift-0.9.3\
then it look like this img
the php code should be like this:
<?php
ini_set('display_error', E_ALL);
$THRIFT_ROOT = __DIR__.'/thrift-0.9.3';
require_once $THRIFT_ROOT . '/Thrift/ClassLoader/ThriftClassLoader.php';
use Thrift\ClassLoader\ThriftClassLoader;
$classLoader = new ThriftClassLoader();
$classLoader->registerNamespace('Thrift', $THRIFT_ROOT);
$classLoader->register();
use Thrift\Transport\TSocket;
use Thrift\Transport\TBufferedTransport;
use Thrift\Protocol\TBinaryProtocolAccelerated;
// (!) include after classLoader
/* Dependencies. In the proper order. */
require_once './hbase-1.2.0-thrift2/THBaseService.php';
require_once './hbase-1.2.0-thrift2/Types.php';
$host = 'xxxxx';
$port = 19090;
$tableName='test';
$rowKey='b';
$socket = new TSocket($host, $port);
$transport = new TBufferedTransport($socket);
$protocol = new TBinaryProtocolAccelerated($transport);
$client = new THBaseServiceClient($protocol);
$transport->open();
$get = new TGet();
$get->row = $rowKey;
$arr = $client->get($tableName, $get);
$data = array();
$results = $arr->columnValues;
foreach($results as $result)
{
$qualifier = (string)$result->qualifier;
$value = $result->value;
$data[$qualifier] = $value;
}
var_dump($data);
$transport->close();

Apache thrift: client timeout issues

I have some Apache Thrift (v.0.6.1) test application with perl-server and php-client.
The behaviour I cannot explain: If we call server-method with invalid argument we see the error in server-output, but php-client stays waiting the response infinitely.
Here are the sources of server:
sub new {
my $classname = shift;
my $self = {};
return bless($self,$classname);
}
sub DateToTimestamp
{
my ($self, $date) = #_;
my $result = CommonAPI::DateToTimestamp($date);
return $result;
}
eval {
my $handler = new RPCHandler;
my $processor = new RPCPerformanceTest::RPCPerformanceTestProcessor($handler);
my $serversocket = new Thrift::ServerSocket(9091);
my $forkingserver = new Thrift::ForkingServer($processor, $serversocket);
print "Starting the server...\n";
$forkingserver->serve();
print "done.\n";
}; if ($#) {
if ($# =~ m/TException/ and exists $#->{message}) {
my $message = $#->{message};
my $code = $#->{code};
my $out = $code . ':' . $message;
die $out;
} else {
die $#;
}
}
and client:
try {
$socket = new TSocket($server_host, $server_port);
$transport = new TBufferedTransport($socket, 1024, 1024);
$protocol = new TBinaryProtocol($transport);
$client = new RPCPerformanceTestClient($protocol);
$transport->open();
$start = microtime(true);
$result = $client->DateToTimestamp('071/26/2011 01:23:45');
var_dump($result);
} catch (Exception $e) {
echo 'Exception: <b>' . $e->getMessage() . '</b>';
}
Why is this happening? Is it my fault? Is it expected behavour?
The Thrift PHP library is a bit broken. You need to manually set the timeouts
E.g.
$socket = new TSocket('host', 9095);
$socket->setSendTimeout(60000);
$socket->setRecvTimeout(60000)
This happens often with protocols that do not supply message length: a client sends more data then the server expects and waits for the server to receive the data. The server receives some of the data, tries to parse it and fails. Now the server-side of the protocol is in errorneous state. If it continues to read the data, it may block. Most probably, the server-side has sent you some error response and is waiting at the same time for the client to receive the response, but that will never happen too.
This is my guess. The best strategy IMHO is to set a time-out for both client and server sockets.

Categories