I have a #ServerEndpoint running on Jboss which holds websocket connections. The customer doesnt want the push of data to be done through the #ServerEndpoint´s #onMessage, but rather a POST-request to some REST endpoint which then pushes the data to the websocket connections (yes, I dont get it either). So my question is; can I get hold of the websocket sessions from the REST-endpoint without opening a server to server connection to the #ServerEndpoint (cause then the security context of the user is broken)?
So I need something like this:
#Controller
#Path("/path")
public class WebsocketController {
#GET
public void doPost(String text) {
//somehow get all websocket connections to the #ServerEndpoint
//then for all sessions do:
session.getBasicRemote().sendText(text);
}
}
Really what any sensible solution would put in the #OnMessage method of the #ServerEndpoint
I ended up with a syncronized list of Sessions I maintain on #OnOpen og #OnClose which holds all open connections. Then I push to these connections from the REST endpoint.
Related
I am using a service fabric Rest API and i need to add some custom headers to my requests.
I am using both a stateless implementation of the service fabric.
When receiving information in the HttpMessageRequest I have the headers there containing information.
I initiate my stateless service using the following code:
// in api controller:
proxy = Proxy.ForMicroservice<IServiceInterface>();
// in the Proxy class:
public static I Create<I>(Uri serviceAddress, UserData data) where I : class, IService
{
var returnval = ServiceProxy.Create<I>(serviceAddress,listenerName:Naming.Listener<I>());
return returnval;
}
I tried the following article (from stack overflow) but it seems to be oriented on WCF. I also expected there to be a more out of the box information about this.
How can i maintain my header information which I received in the original call, or at least transfer this information to my stateless service, without using something like an wrapper Data transfer object?
You can use CallContext to set the headers . After wards,follow this sample on how to send customHeaders to service .
https://github.com/Azure-Samples/service-fabric-dotnet-getting-started/tree/master/Services/ServiceRemotingCustomHeaders/ServiceRemotingCustomHeaders
It looks like you want to do something like this Passing user and auditing information in calls to Reliable Services in Service Fabric transport. You need to set and pass your custome header information in the fabric transport call end then pick that up on the recieving (service side). CallContext can be used to convey that header information from the MethodDispather to any internal service logic without having to rely on expanding your service methods to include it as arguments.
Normally, when we use HTTP requests, we have a specific set of methods/callbacks that would be called when the request succeeds/fails. Each connection request could have its own callback methods, which made structuring of code very easy.
So now that I am trying out Socket.io for a new project, I got all confused. For instance, you emit a message into the socket connection and you're done. no callbacks there. There is no easy way I can know if that actually succeeded or not I've managed to simulate a callback by writing this method:
public void emitRequest(final String event, JSONObject data, final emitResponseListener pListener)
{
mSocket.on(event+"_resp", new Listener() {
#Override
public void call(final Object... args) {
((Activity)c).runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
if (pListener!=null)
{
pListener.onResponseRecieved(data);
}
}
});
}
});
mSocket.emit(event,data);
}
This method listens for a event_resp message from the server after emitting an event. But thats as far as I've got. I have no clue as to how to handle errors for specific emits, so as to update the UI or inform the user .etc.
Sure, there are callback events for the Socket but those are impossible to wire up into the apps flow.
So does anybody know a way to achieve this? I searched a lot but couldn't find anything. I'm using Java Client but generalized answers for any client API are welcome.
You have to change your view - instead of callbacks think about events, and base your design accordingly.
When you make a request to the socket server, generate a unique token. Send the token to the server and have the server send it back with the request response. Using the token you can register a callback that will fire for event matching the request response event and this token.
This way you can execute the calls one after another.
To Cover cases where the server did not return a response, we use timeouts of 30 seconds. About 99.9% of the times we didn't get a response happened due to socket disconnection, so the socket error callback handled that after successful reconnection, without reaching the timeout.
I've installed and configured Prosody server. It listens on standard localhost:5222. Added admin in configuration file - user1#example.com. Every request to server ended up with error:
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" id="" version="1.0">
<stream:error>
<not-well-formed xmlns="urn:ietf:params:xml:ns:xmpp-streams"/>
</stream:error>
</stream:stream>
As a client I would like to use strophe.js. I'm sending only presence stanza ($pres). Here is my code.
'use strict';
angular.module('xmppTestApp')
.controller('ChatCtrl', function () {
var vm = this;
var url = "http://localhost:5222";
var connection = null;
var output = document.getElementById("output");
function log(message) {
var line = document.createElement("div");
line.textContent = message;
output.appendChild(line);
}
function connectHandler(cond) {
if (cond == Strophe.Status.CONNECTED) {
log("connected");
connection.send($pres());
}
else {
log("not connected");
}
}
vm.connectB = function() {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
console.info(url);
console.info(username);
console.info(password);
connection = new Strophe.Connection(url);
connection.connect(username, password, connectHandler);
}
});
In console i see error:
XMLHttpRequest cannot load http://localhost:5222/. No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:9000' is therefore not allowed access.
How can I add Access-Control-Allow-Origin' header to my request?
When I'm trying send request to localhost:5222 (without http) I'm getting:
XMLHttpRequest cannot load localhost:5222. Cross origin requests are only supported for HTTP.
And when I send it through websocket, I'm getting:
WebSocket connection to 'ws://localhost:5222/' failed: Error during WebSocket handshake: Unexpected response code: 200
Fiddler provides me protocol violation report:
The server didn't return properly-formatted HTTP Headers. Maybe missing altogether
(e.g. HTTP/0.9), maybe only \r\r instead of \r\n\r\n?
First and foremost, it looks like you're trying to connect directly to port 5222 (typically used for XMPP), but in order to use Strophe from a client-side webpage, you must use HTTP-Binding (aka BOSH).
XMPP vs BOSH
Strophe speaks XMPP, but it is unique in that it does not actually transmit data using the XMPP protocol, instead it relies on BOSH for this (that is, Bidirectional-streams Over Synchronous HTTP). This is because the XMPP protocol is designed to keep the client and server connected at all times, and we all know this isn't how HTTP works. To put it in simple terms, BOSH allows your HTTP client to asynchronously receive data without having to explicitly make a request for it. If you have more questions regarding BOSH let me know and I'll try my best to explain what is does and why you need it.
You must enable this feature in prosody before connecting with Strophe, check out this link to get setup.
Prosody Docs - Setting up BOSH
Once you've setup BOSH, you will need to change your client side code to use a different address. It is likely that you have setup the path+port for BOSH to something such as :5280/http-bind/. At this point you need to make sure that Strophe is using this URL instead of the actual XMPP port of 5222.
Finally, CORS is required for any resource outside of your websites domain and port. In your example, your client has to make a request to a URL which is running on a different port+domain as the page itself (the connection between Strophe and Prosody). Good news is, Prosody already supports CORS and enabling it is very straightforward. All of this is explained in much further detail on the page I linked earlier.
Hope that helps!
I am trying to implement the work around suggested on this link
http://raibledesigns.com/rd/entry/how_to_do_cross_domain
My existing Servlet on my server looks like
#SuppressWarnings("serial")
public class ContactsServiceImpl extends RemoteServiceServlet implements ContactsService
{
...
How do I modify this to get the cross domain to work. Do I need to make any changes on the client side?
It isn't the GWT Same Origin Policy - it is the browser itself! The browser won't normally allow any XHR call to go out to a server that isn't the same server the page was loaded from.
The link you mentioned lets your server act as a proxy - thats one way to let the client talk to another server. The steps they take (create a servlet that forwards requests, configure it to point at the other server you want to use) do not require changes to the client.
Another option is to use the Cross Origin Resource Sharing - a way for the server to specify that the browser is allowed to contact it, even across domains. The catch: not all browsers support it.
I am trying to consume a restful Web service using camel.
For that I am configuring dynamic endpoint url as the RESTful url is created at the runtime. Everytime I am checking if the particular endpoint url is registered as a route in my camel context using following method of CamelContext class.
Endpoint hasEndpoint(String uri);
In this case, if the endpoint is not registered then I add a route to my camel context using a custom Route Builder.
I am using camel HTTP component for this. This is working fine for me as of now.
However, I believe performance wise this is not good as everytime I have to check if a route is registered with the camel context and if not then register the same before making the webservice call.
Can some body please tell me if there is a better way to consume RESTful Web services in camel?
I also want to know if the RESTful webservice I am consuming uses OAuth 2.0 protocol, do I need to change anything in my code as I am just consuming it?
Regards, Nilotpal
Thanks for your reply.
I am checking if the route is already exists to make sure I don't end up adding duplicate route(s) to the camel context.
Regarding long lived routes and route dynamics, can u please explain a bit regarding this? How do I implement route dynamics?
It would also be helpful if you could point me to some CXF-RS producer example.. I read the documentation of CXFRS but could not understand it clearly.
Thanks
Nilotpal
Exactly why do you need to check if the route is registred or not before making the call? You should perhaps setup a more long lived route and route dynamic towards resfull resources.
As for Rest with camel, I think the HTTP component does a great job, but there are higher level components to use as well, more designed for REST.
CXFRS and Restlet, producer examples for restlet can be found in the Apache Camel source unit tests, such as this RestletProducerGetTest.java.
As for oAuth 2.0, Camel has some oAuth support built-in, especially for google. Look for the gauth component. There is even a tutorial, however it might not be aligned with your case, it still might give some background so you could solve your issues: http://camel.apache.org/tutorial-oauth.html
CamelContext context = new DefaultCamelContext();
My Aim
I am trying to intercept the incoming request and based on the ip of the incoming request i want to invoke dynamic endpoint of get offers
context.addRoutes(new RouteBuilder(){
public void configure(){
from("jetty:localhost:9000/offers")
.process(new Processor(){
public void process(Exchange exchange) throws Exception {
//getting the request object
HttpServletRequest req = exchange.getIn().getBody(HttpServletRequest.class);
//Extracting information from the request
String requestIP=req.getRemoteAddr();
/**
* After getting the ip address i do necessay processing
* and then add a property to exchange object.
* Destination ip address is the address to which i want to
* send my request
*/
exchange.setProperty("operatorAddress",destinationIpAddress);
}
})
.to("direct:getOffers")
.end();
}
});
Now i will invoke the getOffers endpoint
so first i will register it
context.addRoutes(new RouteBuilder(){
public void configure(){
from("direct:getOffers")
.toD("jetty:${property.operatorAddress}/api/v2.0/offers?
bridgeEndpoint=true")
.end();
}
});
so we can access the operatorAddress property of exchange object as
${property.operatorAddress}
also when we have dynamic routes then we need to call
.toD() and not .to()