After a while I got the first part of the Google Channel API working. Now I have some problems with sending a message from the JavaScript client to the server.
Here is the servlet for the Google Channel API connection:
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
if (user != null) {
ChannelService channelService = ChannelServiceFactory.getChannelService();
String token = channelService.createChannel(user.getUserId());
FileReader reader = new FileReader("index.html");
CharBuffer buffer = CharBuffer.allocate(16384);
reader.read(buffer);
reader.close();
String index = new String(buffer.array());
index = index.replaceAll("\\{\\{ token \\}\\}", token);
resp.setContentType("text/html");
resp.getWriter().write(index);
} else {
resp.sendRedirect(userService.createLoginURL(req.getRequestURI()));
}
The index.html looks like following:
<script src="/_ah/channel/jsapi"></script>
<body>
<script type="text/javascript">
onOpened = function() {
alert("opened");
}
var token = "{{ token }}";
var channel = new goog.appengine.Channel(token);
var handler = {
'onopen' : onOpened,
'onmessage' : onMessage,
'onerror' : function() {
},
'onclose' : function() {
}
};
var socket = channel.open(handler);
socket.onopen = onOpened;
socket.onmessage = onMessage;
function sendMessage() {
// Send JSON object to server
}
</script>
<h1>Google Test Channel API</h1>
<form>
<input type="button" value="Send" onclick="sendMessage();">
</form>
</body>
If I load the application I get the opened alert, I believe the connection is working. Now I would like to send a message to the server, if someone clicks on the button.
I read that I have to use the XMLHttpRequest function with POST or GET. But I won’t pass a new url, I
would just pass a value. Is there a way to send a JSON object to the server?
Something like:
{
"message": "This is a JavaClient message!"
}
This doesn't really have much to do with the Chanel API - it's just a standard xhr call back to the server. You can use standard code like this, or use a library such as jquery like this.
If you need to parse javascript into JSON use JSON.stringify().
At the server you can process your request as required, send a response back to the client via standard HTTP or use the Chanel API to send a message not just to the original client, but to all connected clients.
Are you familiair with the channel API blog post of Nick Johnson:
http://blog.notdot.net/2011/07/Using-the-Channel-API-on-App-Engine-for-instant-traffic-analysis
App Engine's Channel API is pretty much only for sending messages from the server->client. It's a one way channel.
That's fine because it's not hard to build the client->server channel, but you do have to build it yourself, it's not for free. You do have to define your own url for the client->server message, then use an XMLHttpRequest to send your message to that url.
There's a small exception in that the Channel API also has a built on mechanism to notify the server of connects/disconnects. Under the cover, these are done using XMLHttpRequests to predefined urls (I think it's something like _ah/channel/disconnect or something. These won't be useful to you since they're automatically called - you can't define when they are called, or the content.
So yeah, just implement your own URL handler, and send your JSON data to that URL.
Related
I have angular code
app.controller('add', function ($scope, $http) {
$scope.add = function() {
$scope.msg = "no connect";
var data = {name:'soso',description:'buba',method:'POST'};
$http.post(host + "/add-component",data)
.then(function (response) {
$scope.msg = response.data;
});
}
});
in my servlet, I want to catch it
resp.setContentType("application/json; charset = utf8");
String name = req.getParameter("name");
String description = req.getParameter("description");
but my name and description both = null;
You are sending data as POST request body, not request parameters. This is documented in the angular docs for post method:
url string
Relative or absolute URL specifying the destination of the request
data *
Request content
Take a look at this answer to see how to read request body.
These days it's easier to use Spring Boot or other frameworks to handle your server side endpoints. There is nothing wrong with using Servlets but you will have to write more code yourself.
I'm trying to communicate with Instagram's API but the reply I get back from my request says that the parameters I passed onto the body weren't detected.
{"error_type":"OAuthException","code":400,"error_message":"You must provide a client_id"}
I tried to send the request by passing a JsonNode or a string inside .post(), like below, but both where unsuccessful.
public CompletionStage<Result> getInstagramToken() {
String code = request().getQueryString("code");
if(code != null) {
WSRequest request = ws.url("https://api.instagram.com/oauth/access_token").setContentType("application/x-wwww-form-urlencoded");
// Json body
/*JsonNode body = Json.newObject()
.put("client_id", insta_clientId)
.put("client_secret", insta_clientSecret)
.put("grant_type", "authorization_code")
.put("redirect_uri", redirect_uri)
.put("code", code);*/
// String body
String body = "client_id="+insta_clientId+"&client_secret="+insta_clientSecret+"&grant_type=authorization_code&redirect_uri="+redirect_uri+"&code="+code;
CompletionStage<WSResponse> response = request.post(body);
return response.thenApplyAsync(resp -> ok(resp.asJson()), exec);
}
return null;
}
The same request passed flawlessly when trying to send it by using a curl command on a terminal or with the Rested plugin on chrome ( where "content type" is set to "application/x-www-form-urlencoded" and the parameters are placed inside "Request body" )
Does anyone have any idea as to how I am supposed to send this request ?
ps: I am also looking for a way to retrieve the value received from my request and store it in a variable instead of returning it to the client.
It seems you are missing a:
.setContentType("application/x-www-form-urlencoded")
Look at our code below. In the post() you can also use a Json object so you can send a HashMap:
CompletionStage<Result> out = ws.url(cbUrl)
.setAuth(<<your user>> , <<your password>>, WSAuthScheme.BASIC)
.setRequestTimeout(Duration.ofSeconds(5))
.setContentType("application/x-www-form-urlencoded")
.post("param=value")
.handle((response, error) -> {
// Was the Chargebee API successful?
if (error == null) {
// Debugging purposes
JsonNode jn = response.asJson();
Logger.debug(Json.toJson(postMap).toString());
Logger.debug(jn.toString());
// Success stuff
return ok("good");
} else {
// Error stuff
return ok("bad");
}
});
Hope this helps you.
I have a periodically calling Ajax call. I use this ajax call to invoke an endpoint. Below I have mentioned my jsp file(polling.jsp). The service has hosted in tomcat server. Expected output from the variable title is "Metallica". But I get below error in firebug without getting the alert.
ReferenceError: Metallica is not defined
alert(Metallica);
I need to check weather the web service is calling time to time as I defined. If I did not put the alert ,
alert(<%=name%>);
then I can see ajax call is working properly in firebug. But I need to put the alert their to get the response form the web service.
polling.jsp
<script>
<%
Client client = Client.create();
%>
var set_delay = 5000,
callout = function () {
$.ajax({
})
.done(function (response) {
<%
WebResource webResource = client
.resource("http://localhost:8080/RESTfulExample/rest/json/metallica/get");
ClientResponse response1 = webResource.accept("application/json")
.get(ClientResponse.class);
if (response1.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response1.getStatus());
}
String output = response1.getEntity(String.class);
Gson gson = new Gson();
Track track=gson.fromJson(output,Track.class);
String name=track.getName().toString();
%>
alert(<%=name%>);
})
.always(function () {
setTimeout(callout, set_delay);
});
};
callout();
</script>
Any help is greatly appreciated. Thanks.
Try wrapping up in double quotes
alert("<%=name%>");
Since <%=name%> will be replaced by value say StackOverflow so you are actually doing
alert(StackOverflow);// will not work as StackOverflow is not an Object/Variable
Hence you need to do alert("StackOverflow");
I am trying to manage a user session by making an ajax request to java code repeatedly
function sendSessionKeepAliveRequest() {
$.get('${URL}/sessionKeepAlive?nd=' + new Date().getTime());
}
and java code (spring framework used) handling this request:
#RequestMapping("/sessionKeepAlive")
public String dummySessionKeepAlive(HttpServletResponse response,
HttpServletRequest request) {
PrintWriter writer = null;
try {
writer = response.getWriter();
} catch (IOException e) {
logger.error(e.getMessage());
}
if (writer != null) {
response.setContentType("application/json");
// Sending an empty JSON response.
Gson gson = new Gson();
writer.write(gson.toJson(""));
}
return null;
}
Now the issue is some times were are getting 302 Found instead of 200 OK which makes jsessionid change and session got time out.I have tested in on IE and FF and both of the browser have same behaviour.
Code is deployed on IBM websphere v7.0
Please help or any direction.Please feel free if any more inputs are required or I need to modify my question.
Kind Regards
You have encountered a so-called redirection: The url of the resource you've requested has changed. The new url is provided in the http header 'Location'.
You can either read out this location and issue another Request using this url or you can set up your response handling code to automatically follow the redirection.
Sample code:
function sendSessionKeepAliveRequest() {
$.ajax(
url: '${URL}/sessionKeepAlive?nd=' + new Date().getTime()
, statusCode: {
302: function ( jqXHR, textStatus, errorThrown ) {
var url_trg = jqXHR.getResponseHeader('Location');
$.get(url_trg);
}
}
});
Update
jquery ajax requests should handle 302 status codes automatically, so there might be some other problem. Could it possibly be a cross-domain issue ?
If the purpose is just only to alive session then no need to use GSON you can pass empty String and add one annotation
#ResposeBody
This will help you to get ajax response.
I'm trying to a write simple REST Java web-service. I use Provider interface on the server side and Dispatch on the clients. I'm trying to transmit a value in header of POST request but there is some problem.
My client code:
private void invoke(Dispatch<Source> dispatch
Object data) {
Map<String, Object> request_context = dispatch.getRequestContext();
request_context.put(MessageContext.HTTP_REQUEST_METHOD, "POST");
request_context.put("org.kpi.asd", "SOME TEXT");
StreamSource source = make_stream_source(data.toString());
dispatch.invoke(source);
}
My server code:
public Source invoke(Source request) {
// Filter on the HTTP request verb
if (ws_ctx == null) throw new RuntimeException("DI failed on ws_ctx.");
// Grab the message context and extract the request verb.
MessageContext msg_ctx = ws_ctx.getMessageContext();
String aaa = (String) msg_ctx.get("org.kpi.asd");
}
On server: aaa is null. I can't understand why. Help me, please (:
the message context is not where you set arbitrary http headers. there is another property in the message context which contains the http headers, see HTTP_REQUEST_HEADERS.