How data is sent from client to (multi-service) server in gRPC - web-services

I am using the gRPC client server framework in one of my application (speech recognition). There are a few important things I want to clarify with my observations.
1. How the optional data field sent, when it is not populated by the client?
Let's see this below example: (assume proto3 is used so all the fields are optional by default)
service NameStudent {
rpc GetRoll(Student) returns (Details) {}
}
#Student'd details
message Student{
int32 roll = 1;
string name = 2;
string gender = 4;
int32 age = 3;
DOB dateofbirth = 5;
}
#Students Date of Birth
message DOB {
int32 dd = 1;
int32 mm = 2;
int32 yy = 3;
}
#Parent's details
message Parent{
string parent =1;
}
#Students all details (includes student + parent)
message Details {
Student student = 1;
Parent parent = 4;
}
Assume that the service takes (input from client) some of the student details, say roll, name, and age, and return that student's (all) details
so now if instead of sending all 3 details (i.e. roll, name and age), even any one or two details can also be sent and (logically assume that) the service works.
In such cases, will the server receive all fields (with blanks/NULLs for omitted fields) or will the client not send that omitted information at all? (see below representations of binary data sent from client)
// roll and name filled
// age is left blank
// gender and DOB are always sent blank from client
{
roll: 170012,
name: "John Doe",
age: ,
gender: "",
dateofbirth: {
dd: ,
mm: ,
yy:
}
}
OR
//only roll and name is sent and rest is just not sent
{
roll: 170012,
name: "John Doe"
}
2. Possible to connect single stub for two services?
If the server offers 2 services and I am making a client stub, will I be able to connect 2 channels from same stub to the same server accessing 2 different services of it?

Question 1
Take a look at this protobuf documentation. In particular:
For any non-repeated fields in proto3, or optional fields in proto2,
the encoded message may or may not have a key-value pair with that
field number.
In practice though, I have observed that optional fields with default values are omitted in the serialization. When the protobuf is deserialized, the parser will interpret the missing field as the default value. You can observe this behavior yourself by using the SerializeToString() method on Python protobuf objects.
Question 2
It's absolutely possible to attach multiple gRPC services to the same server and to interact with multiple services from the same client-side channel. gRPC uses HTTP2 paths to differentiate between multiple services attached to the same server. Take a look at this gRPC Python generated code for an example of that. add_GreeterServicer_to_server associates a user-defined handler with the path /helloworld.Greeter/SayHello, which the stub then uses to identify that service on the server.

Related

Why are my SMS messages sent via Amazon SNS not being received by Indian phone numbers?

I am trying to send text SMS using Amazon SNS in my Springboot application.
This is the configuration class:
#Configuration
#ConfigurationProperties("aws")
public class AwsConfig {
private String accessKeyId;
private String secretAccessKey;
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getSecretAccessKey() {
return secretAccessKey;
}
public void setSecretAccessKey(String secretAccessKey) {
this.secretAccessKey = secretAccessKey;
}
public AWSStaticCredentialsProvider awsCredentials() {
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey );
return new AWSStaticCredentialsProvider(credentials);
}
#Bean
public AmazonSimpleEmailService getAmazonSimpleEmailService() {
return AmazonSimpleEmailServiceClientBuilder.standard().withCredentials(awsCredentials())
.withRegion("us-east-1").build();
}
#Bean
public AmazonSNS getAmazonSNS() {
return AmazonSNSClientBuilder.standard().withCredentials(awsCredentials())
.withRegion("us-east-1").build();
}
}
This is the class to send messages:
#Service
public class SmsSendingServiceImpl {
#Autowired
private AmazonSNS amazonSNS;
public void sendSMS()
{
Map<String, MessageAttributeValue> smsAttributes = new HashMap<String, MessageAttributeValue>();
smsAttributes.put("AWS.SNS.SMS.SenderID", new MessageAttributeValue()
.withStringValue("SENDER")
.withDataType("String"));
smsAttributes.put("AWS.SNS.SMS.SMSType", new MessageAttributeValue()
.withStringValue("Transactional")
.withDataType("String"));
try {
PublishResult result = amazonSNS.publish(new PublishRequest()
.withMessage("This is a test sms.")
.withPhoneNumber("+91-**********").withMessageAttributes(smsAttributes));
System.out.println("Messsage Sent. "+result.getMessageId());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
On calling sendSMS() I do get the Message Sent. message in the console output, but no SMS is being received on the phone number mentioned.
I have tried several different phone numbers for this. None of them are receiving any messages.
It might be worth mentioning that all these numbers are Indian.
Can someone please point out what might be the cause for this?
This is the YouTube video I'm referring to.
The issue you are facing is that India is a country that has special requirements for using a non-numeric sender ID for SMS messages.
Based on Supported Regions and countries documentation for SNS:
Country or region ISO code Supports sender IDs Supports two-way SMS (Amazon Pinpoint only)
India IN Yes3 Yes
Note that the Supports sender IDs column for India is marked as Yes3.
Notes section states:
Senders are required to use a pre-registered alphabetic sender ID. Additional registration steps are required. For more information, see Special requirements for sending SMS messages to recipients in India.
For your origination identity, you can either have origination numbers or sender IDs.
In your case, you cannot opt to use origination numbers as Indian laws require the use of sender IDs instead.
The opposite situation also exists as countries like Canada, China, and the United States require the use of origination numbers (read: U.S. product number comparison for different number types for the number you need to purchase & the SMS cost calculator).
From AWS:
This feature (origination numbers) does not apply when sending SMS to countries where local limitations, laws, or regulations require the use of Sender Ids in the place of origination numbers, for example India.
Therefore, you must follow the Special requirements for sending SMS messages to recipients in India guide. This is what is meant by Additional registration steps are required above.
Unfortunately, there is no workaround for local country laws that AWS apparently needs to abide by.
That said, there may be domestic services that can "circumvent" AWS's legal restriction (as they are domestic/may have special contracts with telecoms etc.). If you don't want to/can't register a sender ID, other services may also be worth looking at.

WSO2 Stream Processor : Correlation during http response handling for http service calls

I have a hosted http service that accepts a trend data and returns some output. This service is accessed in siddhi query language as follows:
#sink(type='http-request', sink.id='trends',
publisher.url='${SERVICE_URL}', #map(type='json', #payload(""" {"trend":{{trendArray}} } """) ) )
define stream Request(item string, trendArray string);
#source(type='http-response' , sink.id='trends', http.status.code='200',
#map(type='json', #attributes(stock = '<HOW_TO_GET_THIS_VALUE>', output = "<HOW_TO_GET_THIS_VALUE>")
) )
define stream Response(item string, output string);
The http request(and response) payload doesn't include item name.
when the response comes we would like to assign item name against which we scored the output - marked as HOW_TO_GET_THIS_VALUE above.
How to accomplish this in siddhi query ?
How to treat the response data of as-is as pass to the field ?
I did not see a description of this scenario in siddhi. If not supported, it will good to know details of a custom extension (based out of http extension) for this scenario. Solution to add a proxy layer for http call is less desired.
After some experiments , HOW_TO_GET_THIS_VALUE = 'trp:item'. The http sink should also have this field even though its not used in payload.

How can I use Apollo/GraphQL to incrementally/progressively query a datasource?

I have a query like this in my React/Apollo application:
const APPLICATIONS_QUERY = gql`
{
applications {
id
applicationType {
name
}
customer {
id
isActive
name
shortName
displayTimezone
}
deployments {
id
created
user {
id
username
}
}
baseUrl
customerIdentifier
hostInformation
kibanaUrl
sentryIssues
sentryShortName
serviceClass
updown
updownToken
}
}
`;
The majority of the items in the query are in a database and so the query is quick. But a couple of the items, like sentryIssues and updown rely on external API calls, so they make the duration of the query very long.
I'd like to split the query into the database portion and the external API portion so I can show the applications table immediately and add loading spinners for the two columns that hit an external API... But I can't find a good example of incremental/progressive querying or merging the results of two queries with Apollo.
This is a good example of where the #defer directive would be helpful. You can indicate which fields you want to defer for a given query like this:
const APPLICATIONS_QUERY = gql`
{
applications {
id
applicationType {
name
}
customer #defer {
id
isActive
name
shortName
displayTimezone
}
}
}
`
In this case, the client will make one request but receive 2 responses -- the initial response with all the requested fields sans customer and a second "patch" response with just the customer field that's fired once that resolver is finished. The client does the heavy lifting and pieces these two responses together for you -- there's no additional code necessary.
Please be aware that only nullable fields can be deferred, since the initial value sent with the first response will always be null. As a bonus, react-apollo exposes a loadingState property that you can use to check the loading state for your deferred fields:
<Query query={APPLICATIONS_QUERY}>
{({ loading, error, data, loadingState }) => {
const customerComponent = loadingState.applications.customer
? <CustomerInfo customer={data.applications.customer} />
: <LoadingIndicator />
// ...
}}
</Query>
The only downside is this is an experimental feature, so at the moment you have to install the alpha preview version of both apollo-server and the client libraries to use it.
See the docs for full details.

Accessing Current Recipient in Sitecore 8 Email Experience Manager

How do you get the raw contact id from the ec_contact_id on the URL created by EXM?
We are using Sitecore's EXM to send emails containing links for surveys to recipients. When the recipient takes the survey we want to tie the response back to the recipient. Since EXM puts a unique Id, ec_contact_id, for the contact (encrypted) we want to use that to determine the recipient versus adding our own custom id.
We found this article, https://briancaos.wordpress.com/2015/04/27/sitecore-8-exm-get-the-email-recipient-from-a-sublayout/, and tried implementing it in the Sitecore controller that gets called when the recipient clicks on the link but the resulting recipient name comes back as empty. We don't have a "sc_item_id" value so we tried "_id" and "ec_message_id" in its place but neither value produced a valid contact Id or recipient name. We also tried looking in MongoDB with the decrypted contactId but couldn't find a match.
You could try somthing like this:
//get value of the ec_contact_id parameter for current request
string queryString = WebUtil.GetQueryString( Sitecore.Modules.EmailCampaign.GlobalSettings.AnalyticsContactIdQueryKey);
var shortID = ShortID.TryParse(queryString, out shortID);
System.Guid contactId;
// where initializationVector is System.Guid of your email message item.
using (var cryptoServiceProvider = new GuidCryptoServiceProvider(System.Text.Encoding.UTF8.GetBytes(GlobalSettings.PrivateKey), initializationVector.ToByteArray()))
{
contactId = cryptoServiceProvider.Decrypt(shortID.Guid);
}
When you create a new user in an email list, Sitecore creates a record in the xDB Mongo database. You should be able to get the email address from the users profile.
Tracker.Current.Contact.GetFacet<IContactEmailAddresses>("Emails").Entries[Tracker.Current.Contact.GetFacet<IContactEmailAddresses>("Emails").Preferred]
Tracker.Current.Contact.GetFacet<IContactEmailAddresses>("Emails").Entries["work_email"]

Email clients for Dynamics AX

I am wondering how the process of sending email is working between Dynamics Ax client and Email client that is set for the server as default email client.
First of all can Dynamics Ax use alternative email clients (not outlook) for sending emails and second of all is Dynamics Ax sending whole configuration to the client, or client has to be configured by itself.
Right now I am experiencing unknown error while trying to send email using Windows Live Mail.
Dynamics AX uses MAPI for client mail.
You can use the SysINetMail::sendEMail method to send a simple mail using this.
If you mail in batch another option is to use SMTP mail using SysEmailTable::sendMail.
This requires the use of mail templates.
I know this is an old question but if someone else needs it...
I am using this on a Dynamics AX 2009 and it works like a charm :)
server static boolean sendEmail(EmplId _fromEmplId, EmplId _toEmplId, str _subject, str message, EmailPriority _priority = EmailPriority::Normal)
{
boolean ok = true;
SysEmailBatch emailBatch;
EmplTable fromEmplTable;
EmplTable toEmplTable;
Email fromEmail;
Email toEmail;
;
changecompany( -- TO YOUR MASTER COMPANY --)
{
fromEmplTable = EmplTable::find(_fromEmplId);
toEmplTable = EmplTable::find(_toEmplId);
fromEmail = fromEmplTable.email();
toEmail = toEmplTable.email();
if (! fromEmail)
{
ok = checkFailed(strfmt("no email set up for %1", _fromEmplId));
}
if (! toEmail)
{
ok = checkFailed(strfmt("no email set up for %1", _toEmplId));
}
if (ok)
{
emailBatch = SysEmailBatch::construct();
emailBatch.parmSendername(fromEmplTable.name());
emailBatch.parmSenderAddr(fromEmplTable.email());
emailBatch.parmEmailAddr(toEmplTable.email());
emailBatch.parmPriority(_priority);
emailBatch.parmSubject(_subject);
emailBatch.parmMessageBody(_message);
emailBatch.run();
}
}
return ok;
}
Using SysOutgoingEmailTable and SysOutgoingEmailData you can send email to recipient of any domain and attach files too.
you have following fields:
outgoingEmailTable.EmailItemId
outgoingEmailTable.IsSystemEmail
outgoingEmailTable.Sender
outgoingEmailTable.SenderName
outgoingEmailTable.Recipient
outgoingEmailTable.Subject
outgoingEmailTable.Priority
outgoingEmailTable.WithRetries
outgoingEmailTable.RetryNum
outgoingEmailTable.UserId
outgoingEmailTable.Status
outgoingEmailTable.Message
outgoingEmailTable.TemplateId
outgoingEmailTable.LatestStatusChangeDateTime
outgoingEmailData.EmailItemId
outgoingEmailData.FileName
outgoingEmailData.EmailDataType
outgoingEmailData.FileExtension
insert respective email detail in these tables and you are good to go. Further if it gives permission error do add permission set with
CodeAccessPermission::assertMultiple .