Message failure in channel api - google-app-engine

I am running a gae web app on localhost.
I have successfully generated a token from goog.channel and send it to client. Where client is able to accept the token and tries to open connection. The problem is that, I am sending a message from my servlet class and nothing is happening in client side.
Below are my codes:
Server Side:
//for generating token
ChannelService channelService=ChannelServiceFactory.getChannelService();
token = channelService.createChannel(userid);
//for sending message
ChannelService channelService=ChannelServiceFactory.getChannelService();
channelService.sendMessage(new ChannelMessage(userid, message));
//in appengine-web.xml
<inbound-services>
<service>channel_presence</service>
</inbound-services>
Javascript:
function getToken(){
var xmlhttpreq=new XMLHttpRequest();
xmlhttpreq.open('GET',host+'/channelapi_token?q='+user,false);
xmlhttpreq.send();
xmlhttpreq.onreadystatechange=alert(xmlhttpreq.responseText);
token=xmlhttpreq.responseText;
setChannel();
}
function setChannel(){
alert(token);//iam receiving right token here
channel=new goog.appengine.Channel(token);
socket=channel.open();
socket.open=alert('socket opened');//this message alerts
socket.onmessage=alert('socket onmessage');//this message alerts
socket.onerror=alert('socket onerror');//this message alerts
socket.onclose=alert('socket onclose');//this message alerts
}
There are no exceptions while sending message from channelservice.
Also the client side is repeatly making a get request to my server:
http://localhost:8888/_ah/channel/dev?command=poll&channel=channel-h1yphg-vivems#gmail.com&client=connection-3
What's the wrong happening here?
Thanks in advance.

You're calling alert(...) and assigning its return value to your message handlers. You should assign a function to these handlers instead:
socket.onopen = function() {
alert('socket opened');
};
// etc
// Note that message takes a parameter:
socket.onmessage = function(evt) {
alert('got message: ' + evt.data);
};
Note you can also do this like:
function onMessage(evt) {
// do something
}
socket.onmessage = onMessage;
Note that you're not assigning onMessage(), which will call onMessage and assign its return value.

Related

report state fails with unauthorized, Google Home action

I'm sending a report state request in my onExecute handler. It fails with:
io.grpc.StatusRuntimeException: UNAUTHENTICATED: Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.
at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:233)
at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:214)
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:139)
at com.google.home.graph.v1.HomeGraphApiServiceGrpc$HomeGraphApiServiceBlockingStub.reportStateAndNotification(HomeGraphApiServiceGrpc.java:425)
at com.google.actions.api.smarthome.SmartHomeApp.reportState(SmartHomeApp.kt:132)
[snip]
I don't see how this is possible since I use the SmartHomeApp to make the request, the same SmartHomeApp that receives sync, query, execute, disconnect. Here's my code:
var state = new HashMap();
state.put("openPercent", 50); // etc
SmartHomeApp app = ... // this is what received the onExecute
app.reportState(ReportStateAndNotificationRequest.newBuilder()
.setRequestId(request.requestId) // onExecute requestId
.setAgentUserId(userId) // hardcoded user
.setPayload(StateAndNotificationPayload.newBuilder()
.setDevices(ReportStateAndNotificationDevice.newBuilder()
.setStates(Struct.newBuilder()
// toValue converts the state to a protobuf value, see data below
.putFields("kitchenDoor", UtilProtoBuf.toValue(state))
.build()
).build()
).build()
).build());
The toString for the ReportStateAndNotificationRequest so you can see the data:
request_id: "16744804305948869781"
agent_user_id: "123"
payload {
devices {
states {
fields {
key: "kitchenDoor"
value {
struct_value {
fields {
key: "openPercent"
value {
number_value: 50.0
}
}
}
}
}
}
}
}
Though you can receive inbound requests, you are not immediately able to make outbound requests back to Google. First you must activate the HomeGraph API and download a service account key.
Then add that to your SmartHomeApp:
// Get service account key from file
FileInputStream stream = new FileInputStream("service-account-key.json");
GoogleCredentials credentials = GoogleCredentials.fromStream(stream);
mySmartHomeApp.setCredentials(credentials);
That should resolve your authorization issue.

ANgular js show always email successfully sent although not sent

I want to send mail to user i succeeded for that using spring boot and angular but i have a problem is that in my console always show me the message that my mail: succeesfuly sent: as mail is sent to user:
this is my angular js controller.js:
$scope.sentMail = function() { var data = new FormData();var mail= $scope.account.mail;
console.log('test 1 :', $scope.account.mail);
console.log("sent mail");
$http.post(_contextPath + '/sentEmail',mail).then(Failure)
.catch(Success);
function Success(success) {
// console.log(response.data);
console.log(' email is successfully sent:', $scope.account.mail);
}
function Failure(error) {
console.log('A problem occurred while sending an email.');
}
}
this is my controller.java:
#RequestMapping(value = "/sentEmail", method = RequestMethod.POST, headers = "Accept=application/json")
public ModelAndView processForgotPasswordForm(ModelAndView modelAndView, HttpServletRequest request, #RequestBody String mail) throws MessagingException
{
System.out.println("print");
User optional= usersService.findByEmail(mail);
if((optional== null))
{
modelAndView.addObject("errorMessage", "We didn't find an account for that e-mail address.");
}
else{
optional.setResetToken(UUID.randomUUID().toString());
usersService.save(optional);
String appUrl = request.getScheme() + "://" + request.getServerName();
SimpleMailMessage passwordResetEmail = new SimpleMailMessage();
passwordResetEmail.setFrom("test#test.com");
passwordResetEmail.setTo(optional.getUserEmail());
passwordResetEmail.setSubject("Password Reset Request");
passwordResetEmail.setText("Hello "+ optional.getUserFirstname()+" "+ optional.getUserLastname()+", \n \n You recently request to reset your password for rotana platform. Please click the link below to reset it : \n \n"+ appUrl +":8080/neorchaWEBPlatform"+ "/reset?token=" + optional.getResetToken()
+"\n \n if you did not request a password reset, please ignore email or reply to let us know.\n \n Thanks, \n \n Rotana Group \n \n P.S. We also love hearing from you and helping you with any issues you have. Please reply to this email if you want to ask a question.");
modelAndView.addObject("ResetMessage", "An e-mail has been sent to " + optional.getUserEmail());
emailService.sendEmail(passwordResetEmail);
}
modelAndView.setViewName("forgotPassword");
return modelAndView;
}
any help,thanks in advance.
.then will handle 'successful' responses. .catch will handle any errors in your success or error functions. You don't have an error function registered. I believe your code should be setup something like this:
$http.post(_contextPath + '/sentEmail',mail).then(Success, Failure)
.catch(UnexpectedError);
function Success(success) {
// console.log(response.data);
console.log(' email is successfully sent:', $scope.account.mail);
}
function Failure(error) {
console.log('A problem occurred while sending an email.');
}
function UnexpectedError(error) {
console.log('Something unexpected happened in Success() or Failure()');
}
The success and error callbacks look at the status being returned by your server. From the Angular documentation:
A response status code between 200 and 299 is considered a success
status and will result in the success callback being called. Any
response status code outside of that range is considered an error
status and will result in the error callback being called. Also,
status codes less than -1 are normalized to zero. -1 usually means the
request was aborted, e.g. using a config.timeout. Note that if the
response is a redirect, XMLHttpRequest will transparently follow it,
meaning that the outcome (success or error) will be determined by the
final response status code.
see: https://docs.angularjs.org/api/ng/service/$http

SignalR, not getting data from server in client

In IE all serverside send method aint delivering data to the client function. I works in all other browsers.
The method is hit, but no data in the response.
(SignalR logging) SignalR: Triggering client hub event 'ping' on hub 'chat'.
Serverside C#/Signalr:
public override Task OnReconnected()
{
var info = "ORC";
Clients.Caller.ping("OnReconnected", info);
return base.OnReconnected();
}
Clientside Angular:
chat.client.ping = onPing;
function onPing(note, info) {
if (info == 'OCO') {
foo();
}
console.log(note)
}
I have disabled ajax cache: $.ajaxSetup({ cache: false });
Stil no data is send back to the client.
Any ideas to solve this problem?

SignalR + WebAPI + AngularJS + HubContext, Client's still don't receive messages

For the last few days I have been trying to implement SignalR into my AngularJS/WebAPI application.
I have been able to successfully send/receive messages from client to client, however when I push messages purely from the Server, none of the clients receive any messages.
I have seen many people having the same problem, the answer always seems to be using GlobalHost.ConnectionManager.GetHubContext which I have been implementing, without error, however the clients still don't receive any of the messages.
I thought that perhaps it's because WebAPI calls are asynchronous and and therefore takes place on a different thread, but I can't be sure. Please could someone have a look and tell me what I'm doing wrong.
This is my Hub Class:
public class ChatHub : Hub
{
public void Send(string name, string message)
{
// Call the broadcastMessage
Clients.All.broadcastMessage(name, message);
}
public void RunMe()
{
System.Diagnostics.Debug.WriteLine("Client Started");
}
public static void Notify(string name, string message)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
hubContext.Clients.All.broadcastMessage(name, message);
}
}
This is the Angular Controller in Javascript:
$scope.chat = $.connection.chatHub;
$scope.chat.client.broadcastMessage = function (name, message) {
$scope.$apply(function () {
var scope = angular.element($('#discussion')).scope();
scope.chatMessage = message;
alert(message);
});
};
$.connection.hub.start()
.done(function ()
{
console.log('Now connected, connection ID=' + $.connection.hub.id);
$scope.chat.server.runMe();
})
.fail(function(){ console.log('Could not Connect!'); });
$('#sendmessage').click(function () {
$scope.chat.server.send("SERVER", $('#inputMessage').val());
});
This is the Controller that is trying to notify the clients from the server
public class UserController : ApiController
{
#region METHODS
[ActionName("Create")]
[HttpPost]
public HttpResponseMessage Create(JObject parameters)
{
//DYNAMIC DATA
dynamic data = parameters;
//CHECK IF CALL FAILED
if (data == null)
return Request.CreateResponse(HttpStatusCode.InternalServerError, "Request is null");
//PERFORM REQUEST
using (var svc = new UserService())
{
//SET Parameters
String Username = data.Username;
String Password = data.Password;
//NOTIFY USERS
ChatHub.Notify("SERVER", "SERVER MESSAGE");
//CREATE Response
var response = svc.Create(Username, Password);
//RESPOND
return Request.CreateResponse(HttpStatusCode.OK, response);
}
}
}
So just to reiterate, when the "sendmessage" button is clicked on my UI, it sends a message to the server which is then received again by the clients, this works 100%,
However when I call the static Notify method from the Controller None of the clients receive any messages.
Calling the function does not return any errors.
Please could someone help me!
<!--Reference the SignalR library. -->
<script src="Scripts/jquery.signalR-2.2.0.min.js"></script>
Check your jQuery.signalR version.
If you are using dependency injection, the example at ASP.NET is wrong, you have to set your GlobalHost.DependendcyResolver in the the Global.asax file. not in the startup class.

In GAE Channel API the onmessage is not called

I am building an app for GAE using python API. It is running here. It is a multi-player game. I use the Channel API to communicate game state between players.
But in the app engine the onmessage handler of the channel is not called. The onopen handler is called. onerror or onclose are not called as well. Weird thing is this works perfectly in the local development server.
Is it possible that something like this can work on the development server but not in the app engine itself?
I'll be really really glad if someone can look into following description of my app and help me to figure out what has happened. Thank you.
I looked into this and this questions, but I haven't done those mistakes.
<script>
sendMessage = function(path, opt_param, opt_param2) {
path += '?g=' + state.game_key;
if (opt_param) {
path += '&' + opt_param;
}
if (opt_param2) {
path += '&' + opt_param2;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', path, true);
xhr.send();
};
Above function is used to make a post request to the server.
onOpened = function() {
sendMessage('/resp');
console.log('channel opened');
};
Above is the function I want to be called when the channel is open for the first time. I send a post to the '/resp' address.
onMessage = function(m) {
console.log('message received');
message = JSON.parse(m.data);
//do stuff with message here
};
I want to process the response I get from that request in the above function.
following are onerror and onclose handlers.
onError = function() {
console.log('error occured');
channel = new goog.appengine.Channel('{{ token }}');
socket = channel.open();
};
onClose = function() {
console.log('channel closed');
};
channel = new goog.appengine.Channel('{{ token }}');
socket = channel.open();
socket.onopen = onOpened;
socket.onmessage = onMessage;
socket.onclose = onClose;
socket.onerror = onError;
</script>
This script is at the top of body tag. This works fine in my local development server. But on the app engine,
onOpen function is called.
I can see the request to /resp in the sever logs.
but onMessage is never called. The log 'message received' is not present in the console.
this is the server side.
token = channel.create_channel(user.user_id() + game.user1.user_id() )
url = users.create_logout_url(self.request.uri)
template_values = {
'token' : token,
'id' : pid,
'game_key' : str(game.user1.user_id()),
'url': url
}
path = os.path.join(os.path.dirname(__file__), 'game.html')
self.response.out.write(template.render(path, template_values))
and this is in the request handler for '/resp' request. My application is a multi-player card game. And I want to inform other players that a new player is connected. Even the newly connected player will also get this message.
class Responder(webapp2.RequestHandler):
def post(self):
user = users.get_current_user()
game = OmiGame.get_by_key_name(self.request.get('g'))
if game.user1:
channel.send_message(game.user1.user_id() + game.user1.user_id() , create_message('%s joined.' % user.nickname()))
if game.user2:
channel.send_message(game.user2.user_id() + game.user1.user_id() , create_message('%s joined.' % user.nickname()))
EDIT : user1 is the user who created the game. I want tokens of other players' to be created by adding the user1's user_id and the relevant users user_id. Could something go wrong here?
So when I try this on the local dev server I get these messages perfectly fine. But on the GAE onMessage is not called. This is my app. When the create button is clicked page with above script is loaded and "playernickname connected" should be displayed.
The channel behavior on the dev server and production are somewhat different. On the dev server, the channel client just polls http requests frequently. On production, comet style long polling is used.
I suspect there may be a problem with making the XHR call inside the onOpened handler. In Chrome at least, I see that the next talkgadget GET request used by the channel API is cancelled.
Try calling sendMessage('/resp') outside of the onMessage function. Perhaps enqueue it to get run by using setTimeout so it's called later after you return.

Resources