Project

General

Profile

Send presence outside Presence.java

Keren Meir
Added about 5 years ago

Hi,

I'm running tigase 5.2.0 RC1. I implemented "everyMinute" thread in SessionManager. I want to send presence to my roster and to my other available devices from this function. I'm using:

Presence.sendPresenceBroadcast(StanzaType.available, session, FROM_SUBSCRIBED, results, presence, settings, roster_util);

But it doesn't work. The presence hasn't really been sent.

The parameters are:

@Map settings = new ConcurrentHashMap(10);

settings.put("sm-jid", getComponentId());@

Queue<Packet> results = new ArrayDeque<Packet>(2);

@Element presence = new Element("presence");

presence.setAttribute("from", session.getJID().toString());

presence.setAttribute("xmlns","jabber:client");@

Do you know about any other way to send presence from the SessionManager ?

Thanks


Replies (17)

Added by Wojciech Kapcia TigaseTeam about 5 years ago

  • Could you provide full code?

  • do you use provided results object of creating your own and add to it's queue? (it may be the case from the information provided above thus this would be case of why no presence is being send)

Added by Keren Meir about 5 years ago

This is the main part of the code:

public synchronized void everyMinute() {
    super.everyMinute();

        Element presence = new Element("presence");
    presence.setXMLNS(Presence.CLIENT_XMLNS);
    presence.setAttribute("from", session.getJID().toString());

        Element show = new Element("show");
    show.setCData("away");
    presence.addChild(show);

        session.setPresence(presence);

        RosterAbstract roster_util = RosterFactory.getRosterImplementation(true);

        Queue<Packet> results = new ArrayDeque<Packet>(2);
    Map<String, Object> settings = new ConcurrentHashMap<String, Object>(10);
    settings.put("sm-jid", getComponentId());
        Presence.sendPresenceBroadcast(StanzaType.available, session, FROM_SUBSCRIBED, results, presence, settings, roster_util);
}

Regarding the results object: I create my own as you can see in the code. I check what the results contains in the Presence.java plugin before "sendPresenceBroadcast" and it was empty. Do I need to enter it something?

Thanks

Added by Wojciech Kapcia TigaseTeam about 5 years ago

OK, now I see. In .sendPresenceBroadcast() method you are simply populating created results Queue, but you are not doing with it anything. When you are done with it you should send those packets using: addOutPackets( results );

Added by Keren Meir about 5 years ago

Didn't get it.....

Why in Presence.java I don't need to do nothing after sendPresenceBroadcast(), but here in SessionManager we need? I don't really understand what sendPresenceBroadcast() does....

And if I want to send the same presence packet to my other available resource, I should run Presence.updatePresenceChange(pack, session, results) and addOutPackets( results ); again after?

I mean:

Presence.sendPresenceBroadcast(StanzaType.available, session, FROM_SUBSCRIBED, results, presence, settings, roster_util);
addOutPackets(results);

Presence.updatePresenceChange(pack, session, results);
addOutPackets(results);

A few more question but in the same subject:

  1. If I want to do the same thing (send presence) but from MobileV2.java plugin. What should I do there? like in Presence.java or SessionManager.java?

  2. If I want to send presence to my other resources, should I use Presence.updatePresenceChange or Presence.updateUserResources ? what is the differenet between them?

  3. What is the different between mobileV2 and MobileV3 in version 5.2.0 RC1?

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 5 years ago

Keren,

From your code I can see that you are attempting to do something you are not supposed to do. Instead of working with Tigase API, you are trying to go around the API. If you could explain what is your real ogle or functionality you are trying to implement , simply why are you doing this then perhaps we could give you a useful suggestion.

Added by Keren Meir about 5 years ago

Ok, so what I'm trying to do is:

When the server get MobileV2=true packet (means the user goes to background), after X minutes I want to send to his roster presence of inactive.

So when I get MobileV2=true packet I'm saving this session in a list, and in "everyMinuts" thread I go over the list and check if X minutes passed. If yes - I'm sending presence show=away, status=inactive.

That's why I need to send presence through SessionManager.

Added by Keren Meir about 5 years ago

So, back to the questions:

A few more question but in the same subject:

  1. If I want to do the same thing (send presence) but from MobileV2.java plugin. What should I do there? like in Presence.java or SessionManager.java?

I tried:

Packet pack = Packet.packetInstance(presence);
pack.setPacketFrom(session.getJID());

Queue<Packet> results2 = new ArrayDeque<Packet>(2);
results2.clear();
results2.offer(pack);

//send online presence to my roster
Presence.sendPresenceBroadcast(StanzaType.available, session, FROM_SUBSCRIBED, results2, presence, settings, roster_util);

//send online presence to my other devices
Presence.updatePresenceChange(pack, session, results2);

It is not working (nobody get this presence)

EDIT: I tried using the "results" that already exist (instead of make new results2) but then I get an exception:

EDIT2: The problem is: Presence.updatePresenceChange(pack, session, results2);

How can I send this presence to my other available resource?

2013-12-30 11:56:04.036 [mobile_v2 Queue Worker 1]  WorkerThread.run()        SEVERE:   tigase.server.xmppsession.SessionManager$ProcessorWorkerThread,(mobile_v2 Queue Worker 1) Exception during packet processing: from=c2s@domain/127.0.0.1_5222_127.0.0.1_60605, to=sess-man@domain, DATA=<iq id="xx" from="user4@domain/Psi" type="set" xmlns="jabber:client"> <mobile enable="false" xmlns="http://tigase.org/protocol/mobile#v2"/> </iq>, SIZE=176, XMLNS=jabber:client, PRIORITY=NORMAL, PERMISSION=NONE, TYPE=set
java.util.ConcurrentModificationException
    at java.util.ArrayDeque$DeqIterator.next(Unknown Source)
    at tigase.xmpp.impl.MobileV2.filter(MobileV2.java:331)
    at tigase.server.xmppsession.SessionManager.addOutPackets(SessionManager.java:1285)
    at tigase.server.xmppsession.SessionManager$ProcessorWorkerThread.process(SessionManager.java:2755)
    at tigase.util.WorkerThread.run(WorkerThread.java:132)
  1. If I want to send presence to my other resources, should I use Presence.updatePresenceChange or Presence.updateUserResources ? what is the differenet between them?

  2. What is the different between mobileV2 and MobileV3 in version 5.2.0 RC1?

Added by Wojciech Kapcia TigaseTeam about 5 years ago

results object is not thread safe (it's a java.util.ArrayDeque@) thus the exception - you can either synchronize access or create presence broadcast packets in a temporary results Array (like you did at first) and later on add them to global results using @.addAll() method.

As per provided javadoc, if you want to send your own presence change to other resources then you should use @Presence.updateUserResources()@. The other one is broadcast to all active resources presence stanza received from other users, like incoming availability presence, subscription presence and so on...

MobileV3 introduced handling of Stream Management (XEP-0198).

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 5 years ago

Keren Meir wrote:

Ok, so what I'm trying to do is:

When the server get MobileV2=true packet (means the user goes to background), after X minutes I want to send to his roster presence of inactive.

So when I get MobileV2=true packet I'm saving this session in a list, and in "everyMinuts" thread I go over the list and check if X minutes passed. If yes - I'm sending presence show=away, status=inactive.

That's why I need to send presence through SessionManager.

In such a case maybe much simpler solution would be to implement this everyMinute logic in such a way that it would generate and send a single away presence packet which is normally sent by a client. This way you do not have to worry about distributing away presence to all contacts as it would be handled automatically by Tigase Presence plugin.

Added by Keren Meir about 5 years ago

How does this presence looks like? (What is different than what I made?)

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 5 years ago

The presence stanza itself does not have to or from address but the Packet object should have from field set to the user's connectionID.

The main difference is that you do not have to replicate the logic to send presence packets to all user's contacts, direct presence entities, etc....

Added by Keren Meir about 5 years ago

OK, how do I send this single presence?

I tried:

Packet pack = Packet.packetInstance(presence);
pack.setPacketFrom(session.getConnectionId());


Queue<Packet> results = new ArrayDeque<Packet>(2);
Map<String, Object> settings = new ConcurrentHashMap<String, Object>(10);
settings.put("sm-jid", getComponentId());
results.offer(pack);
addOutPackets(results);

and it doesn't work...

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 5 years ago

addOutPacket(...) method is not a good choice at all. The purpose of this method is to send stanza out of the SM component. In order to put a packet for processing by SM component you should use: addPacket(...); or addPacketNB();*. The *NB method is non-blocking which is recommended in your case as you execute the code from a timer method.

You do not need results queue and you do not need settings map. Your code could look like this:

    Packet pack = Packet.packetInstance(presence);
    pack.setPacketFrom(session.getConnectionId());
    addPacketNB(pack);

Added by Keren Meir about 5 years ago

Ok Thanks

Now it sends the presence to my roster but not to me and to my other available resources.....

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 5 years ago

What you mean by "sends the presence to my roster"? What you mean by "my roster"?

Added by Keren Meir about 5 years ago

My roster = my contact list

if user1's contact list contains user2 and user3, and also another session of user1 is online, the server sends the presence only to user2 and user3 but not to user1 (both sessions)

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam about 5 years ago

That's a progress then. But it is strange it does not send it to other user's connections. Have you made any modifications to the Presence plugin? Could you give me exact presence packet you generate?

    (1-17/17)