user-a sends a subscription request to user-b. Subscription mode has been set to accept_all. Also, packet listener has been registered for both the users.
When user-a sends a request to user-b this method is called :
private void searchUser(java.awt.event.ActionEvent evt) {
try {
String userToSearch = jTextField1.getText();
if(!xmppParamInit) {
initUXmppP();
xmppParamInit = true;
}
Presence subscribe = new Presence(Presence.Type.subscribe);
userToSearch += "#localhost";
subscribe.setTo(userToSearch);
ofConnection.sendPacket(subscribe); // Send the 'subscribe' packet
}catch(Exception exc) {
exc.printStackTrace();
}
}
Prior to this method, following are called :
private void startPLThread() { // start packet-listener-thread
Runnable r = new Runnable() {
#Override
public void run() {
startPL();
}
};
new Thread(r,"packet listener thread").start();
}
private void startPL() {
PacketListener pListener = new PacketListener() {
#Override
public void processPacket(Packet packet) {System.out.println("Inside process packet");
if(packet instanceof Presence) {
Presence presence = (Presence) packet;
Presence subscription = new Presence(Presence.Type.subscribe);
subscription.setTo(presence.getFrom());
System.out.println("presence.getFrom : " + presence.getFrom());
ofConnection.sendPacket(subscription);
}
}
};
PacketFilter pFilter = new PacketFilter() {
#Override
public boolean accept(Packet packet) {
return true;
}
};
ofConnection.addPacketListener(pListener, pFilter);
}
The problem is user-a can see user-b in his roster but user-b cannot see user-a in its roster. I do not understand the reason for this. What could be the problem ?
Subscription mode has been set to accept_all in this method that is called from within search user :
private void initUXmppP() { // Initialize user-xmpp-parameters
Roster roster = ofConnection.getRoster();
roster.setSubscriptionMode(Roster.SubscriptionMode.accept_all);
}
It is a GUI application and I tried keeping both the users online
Related
I have been reading zookeeper source code and found that when fetching ToSend message from the queue in FastLeaderElection.WorkerSender, they use poll() instead of take(). Why?
Is poll() better?
Searching the git history, I've found that it started using take(), so there must have been a reason for changing to poll().
public void run() {
while (!stop) {
try {
ToSend m = sendqueue.poll(3000, TimeUnit.MILLISECONDS);
if (m == null) {
continue;
}
process(m);
} catch (InterruptedException e) {
break;
}
}
LOG.info("WorkerSender is down");
}
TL;DR: To check the stop flag.
Change made for ZOOKEEPER-498: Diff of FastLeaderElection.java
Old code:
class WorkerReceiver implements Runnable {
QuorumCnxManager manager;
WorkerReceiver(QuorumCnxManager manager) {
this.manager = manager;
}
public void run() {
Message response;
while (true) {
// Sleeps on receive
try{
response = manager.recvQueue.take();
// Receive new message
LOG.debug("Receive new message.");
New code:
class WorkerReceiver implements Runnable {
volatile boolean stop;
QuorumCnxManager manager;
WorkerReceiver(QuorumCnxManager manager) {
this.stop = false;
this.manager = manager;
}
public void run() {
Message response;
while (!stop) {
// Sleeps on receive
try{
response = manager.recvQueue.poll(3000, TimeUnit.MILLISECONDS);
if(response == null) continue;
// Receive new message
LOG.debug("Receive new message.");
they use poll() instead of take(). Why ?
So they can check the new stop flag every 3 seconds.
I am connecting to Pusher server using JAVA code and the issue is the client (using Java Client library) disconnects after few seconds of making connection to the server and it does not reconnect itself.
Also, the connection status at the java-client shows is CONNECTED, as shown in the onConnectionStateChange() callback method but in the background it seems like it stays disconnected because when I tried pushing a request from the server java client did not receive anything but on reconnect (manually) I get the request.
Code:
#Component
#Slf4j
public class PosWebSocketClient {
private Pusher pusher;
private boolean isConnected = false;
private String pusherAppKey;
private Timer timer;
private Date activeTime;
private boolean isUserLoggedIn = false;
private PusherOptions pusherOptions;
public synchronized void init(String pusherAppKey) {
log.info("Initializing Pusher");
pusher = new Pusher(pusherAppKey/* , pusherOptions() */);
this.pusherAppKey = pusherAppKey;
this.isUserLoggedIn = true;
pusher.connect(new ConnectionEventListener() {
#Override
public void onConnectionStateChange(ConnectionStateChange change) {
log.info("State changed to " + change.getCurrentState() + " from "
+ change.getPreviousState());
if (change.getCurrentState() == ConnectionState.CONNECTED) {
isConnected = true;
} else {
isConnected = false;
}
log.info("isConnected {}", isConnected);
}
#Override
public void onError(String message, String code, Exception e) {
log.info("Error while connecting to the server with {} {} {}", message, code, e.getMessage());
log.error("Exception: - ",e);
}
}, ConnectionState.ALL);
Channel channel = pusher.subscribe("*****");
channel.bind("any-event-1", sendDataListener());
channel.bind("any-event-2", receiveOrderListener());
channel.bind("any-event-3", logOutListener());
channel.bind("any-event-4", getOrderStatusListener());
activeTime = new Date();
/*
* if (timer == null) { timer = new Timer(); timer.schedule(new MyTask(), 0,
* 1000 * 60 * 2); }
*/
}
class MyTask extends TimerTask {
public void run() {
long idleTimeInMinutes = (new Date().getTime() - activeTime.getTime()) / (1000 * 60);
log.info("Pusher Idle Time {} ", idleTimeInMinutes);
if (isUserLoggedIn && idleTimeInMinutes >= 10 && StringUtils.isNotBlank(pusherAppKey)) {
log.info("Pusher idle time is greater than 10 mins, initializing again");
disconnect();
init(pusherAppKey);
}
}
}
private SubscriptionEventListener logOutListener() {
return new SubscriptionEventListener() {
#Override
public void onEvent(PusherEvent pusherEvent) {
}
};
}
private SubscriptionEventListener sendDataListener() {
return new SubscriptionEventListener() {
#Override
public void onEvent(PusherEvent pusherEvent) {
log.info("Received SendData event");
}
};
}
private SubscriptionEventListener receiveOrderListener() {
log.info("Received FetchOrder event");
return new SubscriptionEventListener() {
}
};
}
private SubscriptionEventListener getOrderStatusListener() {
log.info("Received SendStatus event");
return new SubscriptionEventListener() {
}
};
}
public synchronized void disconnect() {
// Disconnect from the service (or become disconnected my network conditions)
if (pusher != null && pusher.getConnection() != null) {
log.info("Disconnecting Pusher");
Channel channel = pusher.getChannel("*****");
channel.unbind("any-event-1", sendDataListener());
channel.unbind("any-event-2", receiveOrderListener());
channel.unbind("any-event-3", logOutListener());
channel.unbind("any-event-4", getOrderStatusListener());
pusher.unsubscribe("*****");
pusher.disconnect();
}
}
public void restart() {
if (StringUtils.isNotBlank(pusherAppKey)) {
log.info("Restarting Pusher");
disconnect();
this.init(this.pusherAppKey);
}
}
/*
* private PusherOptions pusherOptions() { if (pusherOptions == null) {
* pusherOptions = new PusherOptions();
* pusherOptions.setMaxReconnectionAttempts(1000000); } return pusherOptions; }
*/
public boolean isConnected() {
return isConnected;
}
private void setPusherStatus() {
activeTime = new Date();
}
public void userLoggedOut() {
this.isUserLoggedIn = false;
}
}
The maven dependency used is
<dependency>
<groupId>com.pusher</groupId>
<artifactId>pusher-java-client</artifactId>
<version>2.0.0</version>
</dependency>
Can anyone please have a look and let me know the issue with the code or dependency or any property I am missing while making connection to the server ? TIA.
I have a utility class where I attempt to send a message. I also created a custom Handler class to handle the messages response. The problem is that handleMessage(Message msg) is not getting called at all. Is it that I'm understanding something incorrectly?
I've tried playing around with placing the handler in different areas of the app structure but I still don't receive any messages.
Below are the public methods that I use in my utility class to send the message into the queue:
public boolean sendRequestToService(int what, Bundle data){
boolean ok = false;
Message message = new Message();
message.what = what;
if(data!=null){
message.setData(data);
}
if (null != mService) {
try {
mService.send(message);
ok = true;
} catch (RemoteException e) {
e.printStackTrace();
}
}
return ok;
}
private void registerToService() {
try {
Message msg = Message.obtain(null, 14);
Messenger mFromService = new Messenger(new MyAppHandler(this));
msg.replyTo = mFromService;
if (null != mService) {
mService.send(msg);
}
} catch (RemoteException e) {
}
}
/////////////////////////////
//////MyAppHandler.java//////
/////////////////////////////
public class MyAppHandler extends Handler implements BluetoothAPI {
private BluetoothDataListener dataListener;
public MyAppHandler(BluetoothDataListener dataListener){
super();
this.dataListener = dataListener;
}
#Override
public void handleMessage(Message msg) {
System.out.println("handle message");
}
}
I am new to xmpp/asmack in android, i'm looking for a method to listen on my own user state and presence changes on the server.
My target it's restore connection if lost.
I'm using presence by roster, which helps me getting the friends presence but actually not the current user itself.
Any help would be appreciated :)
Best regards,
You have to enable a ReconectionManager.
Example:
XmppManager.config = XMPPTCPConnectionConfiguration.builder()
.setServiceName(serverName)
.setHost(server)
.setPort(port)
.build();
connection = new XMPPTCPConnection(config);
ConnectionListener connectionListener = new ConnectionListener(){...}; //
connection.addConnectionListener( connectionListener );
int RECONNECTION_ATTEMPT_SECONDS = 60;
ReconnectionManager.getInstanceFor(connection).enableAutomaticReconnection();
ReconnectionManager.getInstanceFor(connection).setFixedDelay( RECONNECTION_ATTEMPT_SECONDS );
ReconnectionListener looks like this:
public class ReconnectionListener implements ConnectionListener
{
#Override
public void reconnectionSuccessful()
{
System.out.println( "Connection to chat server restored - You are again online" );
//additional foo when connection restored
}
#Override
public void reconnectionFailed( Exception e )
{
System.out.println("Impossible to reconnect, Chat Server seems to be still unavailable" );
}
#Override
public void reconnectingIn( int seconds )
{
System.out.println( "reconnectingIn fired "+seconds);
}
#Override
public void connectionClosedOnError( Exception e )
{
System.out.println("Connection closed, Chat Server become unavailable" );
//additional foo when connection lost (message to user ?)
}
#Override
public void connectionClosed()
{
// "XMPP connection was closed.");
System.out.println( "Connection closed, Chat Server become unavailable");
}
#Override
public void connected( XMPPConnection connection )
{
System.out.println("connected fired - reconnection management enabled");
}
#Override
public void authenticated( XMPPConnection connection, boolean resumed )
{
System.out.println("authenticated fired");
}
}
If that helped, please don't forget to accept the answer :)
To realize the automatic reconnection, you should utilize the ReconnectionManager, and implement the interface ConnectionListener to get the notification.
Details can be refered in https://ramzandroidarchive.wordpress.com/2016/03/14/handling-connection-break-issue-in-smack-4-1/
There exist another way to reconnect by using a timer:
public class TaxiConnectionListener implements ConnectionListener {
private Timer tExit;
private String username;
private String password;
private int logintime = 2000;
#Override
public void connectionClosed() {
Log.i("TaxiConnectionListener", "disconnect");
XmppConnection.getInstance().closeConnection();
tExit = new Timer();
tExit.schedule(new timetask(), logintime);
}
#Override
public void connectionClosedOnError(Exception e) {
Log.i("TaxiConnectionListener", "failed to disconnect");
boolean error = e.getMessage().equals("stream:error (conflict)");
if (!error) {
XmppConnection.getInstance().closeConnection();
tExit = new Timer();
tExit.schedule(new timetask(), logintime);
}
}
class timetask extends TimerTask {
#Override
public void run() {
username = Utils.getInstance().getSharedPreferences("taxicall",
"account", MainActivity.context);
password = Utils.getInstance().getSharedPreferences("taxicall",
"password", MainActivity.context);
if (username != null && password != null) {
Log.i("TaxiConnectionListener", "logining");
if (XmppConnection.getInstance().login(username, password)) {
Log.i("TaxiConnectionListener", "logined");
} else {
Log.i("TaxiConnectionListener", "reconnect");
tExit.schedule(new timetask(), logintime);
}
}
}
}
#Override
public void reconnectingIn(int arg0) {
}
#Override
public void reconnectionFailed(Exception arg0) {
}
#Override
public void reconnectionSuccessful() {
}
}
You need add a connection listener in your logining method:
TaxiConnectionListener connectionListener = new TaxiConnectionListener();
getConnection().addConnectionListener(connectionListener);
Remove listener in disconnection method:
connection.removeConnectionListener(connectionListener);
I have a Situation where I wrote a simple Producer Consumer model for reading in chunks of data from Bluetooth then every 10k bytes I write that to file. I used a standard P-C Model using a Vector as my message holder. So how do I change this so that multiple Thread consumers can read the same messages, I think the term would be Multicaster? I am actually using this on an Android phone so JMS is probably not an option.
static final int MAXQUEUE = 50000;
private Vector<byte[]> messages = new Vector<byte[]>();
/**
* Put the message in the queue for the Consumer Thread
*/
private synchronized void putMessage(byte[] send) throws InterruptedException {
while ( messages.size() == MAXQUEUE )
wait();
messages.addElement( send );
notify();
}
/**
* This method is called by the consumer to see if any messages in the queue
*/
public synchronized byte[] getMessage()throws InterruptedException {
notify();
while ( messages.size() == 0 && !Thread.interrupted()) {
wait(1);
}
byte[] message = messages.firstElement();
messages.removeElement( message );
return message;
}
I am referencing code from an Oreilly book Message Parser section
Pub-sub mechanism is definitely the way to achieve what you want. I am not sure why developing for Android will restrict you from using JMS, which is as simple a spec as it gets. Check out
this thread on SO.
You should definitely use a queue instead of the Vector!
Give every thread its own queue and, when a new message is received, add() the new message to every thread's queue. For flexibility, a listener pattern may be useful, too.
Edit:
Ok, I feel I should add an example, too:
(Classical observer pattern)
This is the interface, all consumers must implement:
public interface MessageListener {
public void newMessage( byte[] message );
}
A producer might look like this:
public class Producer {
Collection<MessageListener> listeners = new ArrayList<MessageListener>();
// Allow interested parties to register for new messages
public void addListener( MessageListener listener ) {
this.listeners.add( listener );
}
public void removeListener( Object listener ) {
this.listeners.remove( listener );
}
protected void produceMessages() {
byte[] msg = new byte[10];
// Create message and put into msg
// Tell all registered listeners about the new message:
for ( MessageListener l : this.listeners ) {
l.newMessage( msg );
}
}
}
And a consumer class could be (using a blocking queue which does all that wait()ing and notify()ing for us):
public class Consumer implements MessageListener {
BlockingQueue< byte[] > queue = new LinkedBlockingQueue< byte[] >();
// This implements the MessageListener interface:
#Override
public void newMessage( byte[] message ) {
try {
queue.put( message );
} catch (InterruptedException e) {
// won't happen.
}
}
// Execute in another thread:
protected void handleMessages() throws InterruptedException {
while ( true ) {
byte[] newMessage = queue.take();
// handle the new message.
}
}
}
This is what I came up with as an example when digging through some code and modifiying some existing examples.
package test.messaging;
import java.util.ArrayList;
import java.util.concurrent.LinkedBlockingQueue;
public class TestProducerConsumers {
static Broker broker;
public TestProducerConsumers(int maxSize) {
broker = new Broker(maxSize);
Producer p = new Producer();
Consumer c1 = new Consumer("One");
broker.consumers.add(c1);
c1.start();
Consumer c2 = new Consumer("Two");
broker.consumers.add(c2);
c2.start();
p.start();
}
// Test Producer, use your own message producer on a thread to call up
// broker.insert() possibly passing it the message instead.
class Producer extends Thread {
#Override
public void run() {
while (true) {
try {
broker.insert();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread {
String myName;
LinkedBlockingQueue<String> queue;
Consumer(String m) {
this.myName = m;
queue = new LinkedBlockingQueue<String>();
}
#Override
public void run() {
while(!Thread.interrupted()) {
try {
while (queue.size() == 0 && !Thread.interrupted()) {
;
}
while (queue.peek() == null && !Thread.interrupted()) {
;
}
System.out.println("" + myName + " Consumer: " + queue.poll());
} catch (Exception e) { }
}
}
}
class Broker {
public ArrayList<Consumer> consumers = new ArrayList<Consumer>();
int n;
int maxSize;
public Broker(int maxSize) {
n = 0;
this.maxSize = maxSize;
}
synchronized void insert() throws InterruptedException {
// only here for testing don't want it to runaway and
//memory leak, only testing first 100 samples.
if (n == maxSize)
wait();
System.out.println("Producer: " + n++);
for (Consumer c : consumers) {
c.queue.add("Message " + n);
}
}
}
public static void main(String[] args) {
TestProducerConsumers pc = new TestProducerConsumers(100);
}
}