Paho JS can't connect to Mosquitto Server - message-queue

When I try to connect to Mosquitto server through this JS, I receive this error:
WebSocket connection to 'ws://xx.xxx.xxx.xxx:1883/mqtt' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET
I tried from console and it works fine.
I tried with Java client as provider and consumer and it works fine.
So I can't undertand what should I do to have it working.
This is JS:
client = new Paho.MQTT.Client("xx.xxx.xxx.xxx", 1883, "clientId");
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
// connect the client
client.connect({onSuccess:onConnect});
This is Java (working):
#Stateless
#LocalBean
public class PahoManager implements MqttCallback {
MqttClient client;
public void init() {
try {
client = new MqttClient("tcp://192.168.50.10:1883", "pahomqttpublish1");
client.connect();
client.subscribe("pahodemo/test");
} catch (MqttException e) {
e.printStackTrace();
}
}
public void doDemo() {
try {
MqttMessage message = new MqttMessage();
message.setPayload("Ciao Pluto".getBytes());
client.publish("pahodemo/test", message);
//client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
}
#Override
public void connectionLost(Throwable thrwbl) {
System.out.println("Connection Lost");
}
#Override
public void messageArrived(String string, MqttMessage mm) throws Exception {
System.out.println("Message: " + string + mm);
}
#Override
public void deliveryComplete(IMqttDeliveryToken imdt) {
System.out.println("Message delivered");
}
}

As hardillb said, mosquitto does not yet support websockets. If you want native websockets, there are other solutions like HiveMQ. You can see a full list of brokers with websocket support here (you may need to scroll the table to the right). You can learn more about MQTT over websockets in this blog post:
Please make sure, that you are connecting to the websocket port which is usually not 1883. In practice this means, that your TCP MQTT clients connect to port 1883 and your websocket clients to another port like 8000.
The usual disclaimer: I'm one of the HiveMQ developers so this answer may be biased ;-)

You need to use Mosquitto version 1.4 to get websockets support. This has not been released yet, but you can build it yourself. The source is available here:
https://bitbucket.org/oojah/mosquitto/branch/1.4
The other option is to run a websocket to MQTT bridge. You can use the lighttpd module described here:
http://test.mosquitto.org/ws.html

Related

Vert.x httpclient - 3.5.0 throws exception "Connection was closed" intermittently

I have vert.x app which is consuming api REST over json but intermittently I am seeing exception with reason "Connection was closed". Below are my details -
please share your inputs if anything wrong in the configuration. may be creating scheduler or instantiating httpclient ?
on a different note is it advisable to use same http client to call more than 1 different api's on the same host and port ?
Vert.x Version: 3.5.0
import io.vertx.core.http.HttpClient;
private static Scheduler scheduler =
Schedulers.from(Executors.newFixedThreadPool(8));
// http client instantiated at the time of verticle startup
HttpClient httpclient = vertx.createHttpClient(getHttpClientOptions());
public static HttpClientOptions getHttpClientOptions() {
return new HttpClientOptions()
.setKeepAlive(true)
.setMaxPoolSize(100)
.setPipelining(true)
.setDefaultHost(xxxx.xxxx.com)
.setDefaultPort(8084)
.setSsl(true);
}
// invoke api call
public static Single<Response> invokePOSTServiceAsync(String reqBodyStr, String endpointURI) throws Exception {
try{
return Single.create((SingleEmitter<Response> emitter) -> {
HttpClientRequest request = httpClient.post(endpointURI);
request.putHeader("Content-type","application/json")
request.exceptionHandler(error -> {
LOG.error("ExceptionHandler "+error.getMessage());
emitter.onError(new Throwable(" Failure"));
})
.handler(response -> {
int statusCode = response.statusCode();
if (statusCode == 200) {
response.bodyHandler(body -> {
StringBuilder responseData = new StringBuilder();
responseData.append(body);
emitter.onSuccess(new Response(statusCode,responseData.toString(),"","",null));
});
} else {
emitter.onError(new Throwable(" Failure"));
}
})
.putHeader(HttpHeaders.CONTENT_LENGTH, reqBodyStr.length() + "")
.setTimeout(6000)
.write(reqBodyStr)
.end();
}).subscribeOn(scheduler);
}catch(Exception exe){
exe.printStackTrace();
return null;
}
}
My guess is that this is not related to the client. Either your server is being overloaded, or your network is unreliable. If you're consuming service which doesn't belong to you, you also may get throttled, and that's the reason you're seeing this.
In any case, you need to circumvent those problems, as the network is unreliable anyway. Make your POST requests idempotent and introduce retries.

Spring Web Socket - notify the client from the MQ Listener

I am using web-sockets using Spring.
Here is my controller. A simple controller, which would accept a result object and return a result object with populated values. It would publish message to the STOMP topic subscribers "/topic/update".
#Controller
public class ReportController {
#MessageMapping("/charthandler")
#SendTo("/topic/update")
public Result pushMessage(Result r) throws Exception {
Thread.sleep(3000); // simulated delay
Result result = new Result();
result.setTitle("ChartsPage");
return result;
}
}
My Spring Configuration file:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/charthandler").withSockJS();
}
#Bean
public WebSocketHandler chartHandler() {
return new ChartHandler();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
}
I have the following code in javascript, which creates a STOMP Web Socket Client. It is subscribing to the '/topic/update'
var socket = new SockJS('/reportapplication/charthandler/');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/update', function(result) {
console.log(JSON.parse(result.body).title);
});
});
Now i am planning to add a listener(java and not in javascript) which would listen to the Rabbit MQ message, i want to pass the message object to my controller and push all the message to the Web Socket Clients.
I am not sure how to notify all my web-socket clients , when the message is arrived at my MQ listener.
How will i do that?
Is it a good way to create an instance of report controller and call the pushMessage to notify all my web socket clients.
ReportController controller = new ReportController();
controller.pushMessage(report);
Also i'm not sure, if this works. I will try that. I want to know if there is a better approach.
Is there a better approach or better way of doing this?
Maybe if you look at the response Artem Bilan has provided to the following question: Spring, how to broadcast message to connected clients using websockets?
So if your java listener to the Rabbit MQ message is in a service then you can do the following in the same service and call the sendTo marked WS notification endpoint and pass on expected message to go out to the WS clients listening.
#Autowired
private SimpMessagingTemplate brokerMessagingTemplate;
.......
this.brokerMessagingTemplate.convertAndSend("/topic/greetings", "foo");

Configure Spring Data Couchbase on a cluster host address

My data people gave me the http://127.0.0.1:8091/pools url to connect to our Couchbase server and I've been told the pools suffix is the address to all the nodes in the cluster.
I'm using Spring 4.2.0.RELEASE with spring-data-couchbase 2.0.0.M1 against Couchbase 2.5.1 enterprise edition (build-1083)
Now, if I add the above url as is into the getBootstrapHosts list:
#Override
protected List<String> getBootstrapHosts() {
return Collections.singletonList(couchbaseProperties.getHost());
}
I get a number format exception on the 8091/pools value.
But when using the http://127.0.0.1:8091 url I get an invalid password exception.
I reckon the first url is to be used, but not in the way I went for.
There is probably a method I should override in the AbstractCouchbaseConfiguration class, but looking at the source code didn't really enlighten me.
Here is the Couchbase configuration class.
#Configuration
#EnableCouchbaseRepositories(basePackages = { "com.thalasoft.data.couchbase.repository" })
#ComponentScan(nameGenerator = PackageBeanNameGenerator.class, basePackages = { "com.thalasoft.data.couchbase.config" })
#EnableTransactionManagement
public class CouchbaseConfiguration extends AbstractCouchbaseConfiguration {
private static Logger logger = LoggerFactory.getLogger(CouchbaseConfiguration.class);
#Autowired
private CouchbaseProperties couchbaseProperties;
#Override
protected List<String> getBootstrapHosts() {
return Collections.singletonList(couchbaseProperties.getHost());
}
#Override
protected String getBucketName() {
return couchbaseProperties.getBucketName();
}
#Override
protected String getBucketPassword() {
return couchbaseProperties.getBucketPassword();
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
#Bean
public ValidatingCouchbaseEventListener validationEventListener() {
return new ValidatingCouchbaseEventListener(validator());
}
}
The fact that your database administrators gave you 127.0.0.1 as the adress to connect to seem strange, but indeed could be valid if one node of the cluster is running colocated with the client code...
This url-based syntax was the one used for the 1.4.x generation of SDK, and configuration is indeed a bit different in 2.x (reflecting the evolution of the Couchbase SDK between 1.4.x and 2.x): you just need to provide the hostname or ip of each node to bootstrap from, in a list.
You should try with just "127.0.0.1". It is possible also that you need to specify a bucket name and/or a password (ask your administrator). The defaults used by Spring Data Couchbase for each is "default" and "" (empty password), but you can override the getBucketName() and getBucketPassword() methods from AbsctractCouchbaseConfiguration to change that.
PS: the Spring Data Couchbase documentation is available here

Error trying to connect to an mvc server on ms-azure from a windows phone 8 app using webapi

I'm a little bit new to all of these technologies so I'll try to be as clear as I can.
I'm writing a windows phone app that sends data in string format to a server:
public class sendDataControl
{
private string response = "";
public void sendToServer(string FullSTR)
{
try
{
WebClient webClient = new WebClient();
Uri uri = new Uri("http://pricequeryserver.azurewebsites.net/api/ReceiptDataService/?incomingdata=");
webClient.UploadStringAsync(uri,FullSTR);
webClient.UploadStringCompleted += new UploadStringCompletedEventHandler(webClient_UploadStringCompleted);
}
catch (Exception ex)
...
...
}
}
void webClient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
if (e.Error != null)
{
responseXml=e.Error.Message;
MessageBox.Show(responseXml);
return;
}
else
{
responseXml = e.Result;
}
}
}
The server is an MVC4, basic, with api controller I added, that needs to get the data sent from the mobile.
As a test I'm just getting back a string that I send:
public class ReceiptDataServiceController : ApiController
{
private ReceiptContext db = new ReceiptContext();
...
...
public string GetDataFromMobile(string IncomingData)
{
return IncomingData;
}
}
While running the application I get an error via responseXml:
"The remote server returned an error: NotFound".
The server returns the right answer from all kinds of browsers, while on IIS and on the azure but not from the mobile emulator.
Any suggestions?
If you take a look at the documentation for UploadStringAsync overload you are using, you will notice that it sends data using POST method. While in your controller you have only implemented GET. And for your
You have to use other overload of UploadStringAsync, which lets you specify the HTTP VERB to use. And you must specify GET. Your client code should be converted to:
webClient.UploadStringAsync(uri,"GET", FullSTR);
And the best solution for simple GET operations like your is to actually use DownloadStringAsync:
var fullUri = new Uri("http://pricequeryserver.azurewebsites.net/api/ReceiptDataService/?incomingdata=" + FullStr);
webClient.DownloadStringAsync(fullUri);
Anyway, your question has nothing to do with Windows Azure, thus the removed tag.

GWT RPC Call onFailure

I created a Remote Procedure Call. The Server-Side connects to Webservices, to get Information, which it hands over to the Client-Side. This is the Client-Side Code.
public void statusFor(GwtLaneServiceAsync laneProxy){
AsyncCallback<LaneInformation> callback = new AsyncCallback<LaneInformation>()
{
#Override
public void onFailure(Throwable caught)
{
}
#Override
public void onSuccess(LaneInformation information)
{
doStatusForSuccess(information);
}
};
for (Lane lane : this.mainmenu.getSlidePanel().getLaneMenu().getProperLanes().values())
{
if (lane.isChecked().booleanValue())
laneProxy.statusFor("admin", "password", true, lane.getId(), callback);
else
laneProxy.statusFor("admin", "password", false, lane.getId(), callback);
this.laneIndex++;
}
}
Now i wanna do the following...
When the Server can't reach the Webservice, a WebServiceException is thrown. If that happens, I wanna type "Offline" on one of my Buttons of the GUI. BUT I need to tell on which button. It can't be hard coded, cause it depends on which "lane" the Webservice failed.
I need to catch the Exceptions
I need to tell the "onFailure"-Part, on which lane, the Service failed.
Can I somehow deliver the statusFor()-Parameters to that part?
There is no of ways to handle such case. you can throw any custom exception from server side while server can't reach the webservice. then it will come onFailure block. or you can return any message string in response variable. Here response variable you are using LaneInformation bean. so take new variable there like result, and set message as per your requirement.
OnFailure it comes only when any exception occurred or any wrong thing happens in RPC call.
Why not wrap your LaneInformation in a generic response object and add the exception/an error code to that response, to signal that something went wrong on the server side, eg.:
public class RemoteResult<T>
{
T payload;
String errorCode;
}
and
public abstract class AbstractAsyncCallBack<T> implements AsyncCallback<RemoteResult<T>>
{
public void onSuccess( RemoteResult<T> rr )
{
if ( rr.getErrrorCode() != null ) { failure( rr.getErrorCode() ); }
else { success( rr.getPayload() ); }
}
public abstract void success( T payload );
public void failure( String errorCode ) { /* Ignore by default */ }
}
To conclude, you shouldn't throw an exception on the server side when the server can't connect to some other service, you should communicate that nicely to the client, and that's not by (re)throwing the exception :-)
The onFailure() method is mostly for when things go wrong in the RPC communication proper.
Cheers,