I am using asmack library for my chat application.I am using below described code after successful login for getting Muc room information:
MultiUserChat mMultiUserChat = new MultiUserChat(connection,"VjNewMoiosandroid#conference.chat");
mMultiUserChat.join(USERNAME);
try {
if (mMultiUserChat.isJoined()==true) {
RoomInfo roomInfo=mMultiUserChat.getRoomInfo(connection,"VjNewMoiosandroid#conference.chat");}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
I get this error while getting room information ,while i debug and check i am getting room information in log but nothing comes in roomInfo.
10-10 08:55:12.388: W/System.err(1821): java.lang.ClassCastException:
org.jivesoftware.smack.util.PacketParserUtils$2 cannot be cast to
org.jivesoftware.smackx.packet.DiscoverInfo 10-10 08:55:12.428:
W/System.err(1821): at
org.jivesoftware.smackx.ServiceDiscoveryManager.discoverInfo(ServiceDiscoveryManager.java:600)
10-10 08:55:12.458: W/System.err(1821): at
org.jivesoftware.smackx.ServiceDiscoveryManager.discoverInfo(ServiceDiscoveryManager.java:552)
10-10 08:55:12.478: W/System.err(1821): at
com.demo.xmppchat.CopyOfXMPPChatDemoActivity.getRoomInfo(CopyOfXMPPChatDemoActivity.java:469)
My chat room information i received in log
10-10 15:38:10.133: D/SMACK(26035): 03:38:10 PM RCV (1107887640): <iq
from='VjNewMoiosandroid#conference.chat' to='14393671556301070000#chat/Smack'
id='VWaeO-6' type='result'><query xmlns='http://jabber.org/protocol/disco#info'><identity
category='conference' type='text' name='VjNewMoiosandroid'/><feature var='
http://jabber.org/protocol/muc'/><feature var='muc_public'/><feature
var='muc_persistent'/><feature var='muc_open'/><feature var='muc_semianonymous'/><feature
var='muc_moderated'/><feature var='muc_unsecured'/><x xmlns='jabber:x:data'
type='result'><field type='hidden' var='FORM_TYPE'><value>
http://jabber.org/protocol/muc#roominfo</value></field><field label='Room description'
var='muc#roominfo_description'><value></value></field><field label='Number of occupants'
var='muc#roominfo_occupants'><value>1</value></field></x></query></iq>
I was using old asmack jar that is my issue ,I made some changes i used MultiUserChat class getRoomInfo() Method directly in my class
MultiUserChat mMultiUserChat = new MultiUserChat(connection,"VjNewMoiosandroid#conference.chat");
mMultiUserChat.join(USERNAME);
try {
if (mMultiUserChat.isJoined()==true) {
String roomInfo=getRoomInfo(connection, "VjNewMoiosandroid#conference.chat");}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
I made one method as below
public static String getRoomInfo(Connection connection, String room)
throws XMPPException {
String roomInfo="";
try {
ServiceDiscoveryManager serviceDiscoveryManager=new ServiceDiscoveryManager(connection);
DiscoverInfo info = serviceDiscoveryManager.discoverInfo(room);
roomInfo=info.toXML();
} catch (XMPPException e) {
// TODO: handle exception
Log.e("xmpp", e.toString());
}
return roomInfo;
}
Do this way
Replace this line
RoomInfo roomInfo=mMultiUserChat.getRoomInfo(connection,"VjNewMoiosandroid#conference.chat");
With this
RoomInfo roomInfo=MultiUserChat.getRoomInfo(connection,"VjNewMoiosandroid#conference.chat");
Related
I am using Ejabberd as XMPP server and creating xmpp client in smack API.I want to send additional parameter with message.
My code is below :
public static void main(String[] args) throws SmackException,IOException,XMPPException {
XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
.setResource("Smack")
.setSecurityMode(SecurityMode.disabled)
.setServiceName("localhost")
.setHost("localhost")
.setPort(Integer.parseInt("5222"))
.build();
AbstractXMPPConnection conn = new XMPPTCPConnection(config);
try {
conn.setPacketReplyTimeout(10000);
SASLAuthentication.unBlacklistSASLMechanism("PLAIN");
SASLAuthentication.blacklistSASLMechanism("SCRAM-SHA-1");
SASLAuthentication.blacklistSASLMechanism("DIGEST-MD5");
//SASLAuthentication.
conn.connect();
conn.login("test1#localhost","123456");
System.out.println("login successfull");
Message message = new Message();
String stanza = "i am vip";
message.setBody(stanza);
stanza+= "<type>.jpg</type>";
ChatManager manager = ChatManager.getInstanceFor(conn);
manager.createChat("vipul#localhost").sendMessage(message);
message.setBody(stanza);
System.out.println("Message Sent");
} catch (Exception e) {
e.printStackTrace();
}
}
By this code i am able to add type in xmpp stanza but i think it is not preferable way.So i need help to send additional parameter with message.
If i get solution this will be appreciated.
Thanks !!
you can add additional parameter like that-
Message message = new Message();
String stanza = "i am vip";
message.setBody(stanza);
message.addBody("customtag","Custom tag value");
message.addBody("customtag1","Custom tag value1");
and you can get it like-
String customtageValue= message.getBody("customtag");
for more detail check this link
I'm trying to send a Message with Type.headline
This is my code:
public boolean sendText(Chat chat, String text) {
Message message = new Message();
message.setBody(text);
message.setType(Message.Type.headline);
message.setPacketID("id123456");
try {
chat.sendMessage(message);
Log.d("TAG", message.toXML().toString());
return true;
} catch (SmackException.NotConnectedException e) {}
return false;
}
But the XML that is sent, looks like this:
<message id='id123456' to='roee#192.168.0.3' type='chat'>
<body>test message</body>
<thread>ed108b04-4488-423a-a441-ca95284db6c1</thread>
</message>
As you can see, in the XML type='chat' instead of type='headline'.
Why is that and how do I change it?
Because you use a Chat to send the message.
Simply use XMPPConnection.sendStanza(Stanza) (use sendPacket(Stanza) in older Smack versions) to send you message with type headline.
I'm developing a web application that sends an email and has to check, that, in fact this mail has been delivered from my application side as much as possible in few seconds (I don't think you can do more than getting that the email has been delivered to email server, if that email server later cannot later send that email to the user that uses it because it has its inbox full or another situation like this, I think it cannot be helped, although if there's some way I'd like to know about it).
Anyway one thing I think could be checked without problems is if the email address doesn't exist as that gives an inmediate response, according to what I've read this could be done with class MessageException, but I've the following code:
String email=Utils.parseString(req,"email");
[....]
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.starttls.enable","true");
props.put("mail.smtp.EnableSSL.enable","true");
Session s = Session.getInstance(props, null);
MimeMessage message = new MimeMessage(s);
try {
InternetAddress from = new InternetAddress(emailadressthatworks);
message.setFrom(from);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return;
}
try {
InternetAddress to = new InternetAddress(email);
message.addRecipient(Message.RecipientType.TO, to);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
resp.sendRedirect("webpage.jsp");
return;
}
try {
message.setSubject("Subject");
message.setText("message");
Transport.send(message);
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
resp.sendRedirect("webpage.jsp");
return;
}
[....]
And whatever random String I asign to email it never throws an MessagingException in Transport.send(message); so I can redirect it to another jsp web page when I think it should according to what I have read.
Might I be missing something or is it that this class cannot detect that things?
Thanks for your help.
Use the strict InternetAddress constructor and call message.saveChanges() to perform the validation. See
Content-Type syntax check throws exception too late for more details.
See this JavaMail FAQ entry.
Also, it's up to your mail server whether it tries to detect some kinds of errors immediately or whether it queues all requests and only checks for errors later.
I'm trying to build an app to send bulk report emails to many addresses with various hosts. I'm using Javamail and well, I'm still learning it though.
I found an example and try sending emails with my company server as host (let's say xyz company).
here is the sample code
package mailexample;
import javax.mail.*;
import javax.mail.internet.*;
public class MailExample {
public static void send(String smtpHost, int smtpPort,
String from, String to,
String subject, String content) {
try {
java.util.Properties props = new java.util.Properties();
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.port", ""+smtpPort);
Session session = Session.getDefaultInstance(props, null);
//Store store = session.getStore();
//Folder folder = store.getFolder("INBOX");
//System.out.println(folder.getMessage(1));
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
msg.setSubject(subject);
msg.setText(content);
Transport.send(msg);
}
catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
try {
send("mail.xyz.ac", 25, "asdf#xyz.ac", "qwer#xyz.ac",
"title", "content");
}
catch(Exception e) {
e.printStackTrace();
}
}
}
It works fine and I get an error stacktrace when the address is invalid.
But that is only happen if I send an email to the same server/host which is mail.xyz.ac.
If I send an email to some random gmail or ymail addresses (that likely don't exist), my app return success message but nothing happened after that, only a message (like mailer-daemon in gmail) in sender inbox that said it is not delivered.
The problem is, I need to store that message in my database for further notice.
Is it possible to get that message from my app?
The JavaMail FAQ is your friend while learning JavaMail. This entry and this entry address your question. Also, be sure to read the entry about common mistakes.
We have a UCMA 3.0 based application/bot that matches end users with experts. It migrates incoming one-one chat requests from end users into a multi user conference and then invites experts into the resulting multi user conference. The application itself continues to be a participant in the conference. At any given time, there may be several such conferences being brokered by our application but only one per end user. However, a single expert may be participating in more than one conference at the same time.
In our application logs we occasionally see the following exception.
Error in Conference Migration conf call # 63809878 ,Address :sip:xxxxxx#xxx.com;gruu;opaque=app:conf:focus:id:TQRREACE System.InvalidOperationException: Cannot join a different conference after receiving a conference invitation or conference escalation request.
at Microsoft.Rtc.Collaboration.ConferenceSession.VerifyAndGetConferenceAddress(String conferenceUri, String parameterName)
at Microsoft.Rtc.Collaboration.ConferenceSession.BeginJoinCommon(String conferenceUri, ConferenceJoinOptions options, AsyncCallback userCallback, Object state)
at Microsoft.Rtc.Collaboration.ConferenceSession.BeginJoin(String conferenceUri, ConferenceJoinOptions options, AsyncCallback userCallback, Object state)
at a(String A_0, String A_1, String A_2, Boolean A_3, Boolean A_4)
Below is the code snippet used to make conference. Previously this site was an OCS 2007 R2 Installation and was migrated to Lync 2010 Server.
Site is running in mixed mode. It occurs only on production server and we are not able to generate this exception on dev server, we
have tested it after generating more than 15 conferences simultaniously but no luck.
private void CreateAdHohConf(string user1Uri, string user2uri, string subject)
{
Exception exception = null;
// Create conference scheduling details for the conference.
ConferenceScheduleInformation scheduleInfo = new ConferenceScheduleInformation();
// Restrict the conference to invited users only.
scheduleInfo.AccessLevel = ConferenceAccessLevel.Everyone;
// Set a subject for the conference.
scheduleInfo.Subject = subject;
scheduleInfo.Description = subject;
scheduleInfo.ConferenceId = ConferenceServices.GenerateConferenceId();
scheduleInfo.ExpiryTime = System.DateTime.Now.AddHours(8);
scheduleInfo.IsPasscodeOptional = true;
scheduleInfo.PhoneAccessEnabled = false;
// Don't automatically assign a leader.
scheduleInfo.AutomaticLeaderAssignment = AutomaticLeaderAssignment.Everyone;
// Add the caller and recipient as participants.
scheduleInfo.Participants.Add(new ConferenceParticipantInformation("sip:" + user1Uri, ConferencingRole.Leader));
scheduleInfo.Participants.Add(new ConferenceParticipantInformation("sip:" + user2uri, ConferencingRole.Leader));
scheduleInfo.Mcus.Add(new ConferenceMcuInformation(McuType.ApplicationSharing));
scheduleInfo.Mcus.Add(new ConferenceMcuInformation(McuType.InstantMessaging));
scheduleInfo.Mcus.Add(new ConferenceMcuInformation(McuType.AudioVideo));
scheduleInfo.Mcus.Add(new ConferenceMcuInformation(McuType.Meeting));
//Scheduling conference
ConferenceServices objLocalConfSvc = lyncAgent.LocalEndpoint.ConferenceServices;
Conference confSession = null;
objLocalConfSvc.BeginScheduleConference(scheduleInfo,
result =>
{
try
{
confSession = objLocalConfSvc.EndScheduleConference(result);
}
catch (RealTimeException rtex)
{
exception = rtex;
}
catch (Exception ex)
{
exception = ex;
}
finally
{
_waitForConferenceScheduling.Set();
}
}, objLocalConfSvc);
_waitForConferenceScheduling.WaitOne();
//Begin Join conference
ConferenceSession objLocalConfSession=this.call.Conversation.ConferenceSession;
try
{
ConferenceJoinOptions joinOptions = new ConferenceJoinOptions() { CanManageLobby = false, JoinMode = JoinMode.Default };
objLocalConfSession.BeginJoin(new RealTimeAddress(confSession.ConferenceUri).Uri, joinOptions,
result => {
try
{
objLocalConfSession.EndJoin(result);
}
catch (Exception ex)
{
exception = ex;
}
finally
{
//Again, for sync. reasons.
_waitForConferenceJoin.Set();
}
}
, this.call.Conversation.ConferenceSession);
// Wait until join completes.new RealTimeAddress(this._conference.ConferenceUri).Uri,
_waitForConferenceJoin.WaitOne();
}
catch (InvalidOperationException ioex)
{
exception = ioex;
}
catch (Exception ex)
{
exception = ex;
}
//Begin Escalation
Conversation objLocalConv= this.call.Conversation;
try
{
objLocalConv.BeginEscalateToConference(
result =>
{
try
{
objLocalConv.EndEscalateToConference(result);
}
catch (Exception ex)
{
exception = ex;
}
finally
{
//Sync It
_waitForEscalation.Set();
}
}
, objLocalConv);
// Wait until escalation completes.
_waitForEscalation.WaitOne();
}
catch (InvalidOperationException ioex)
{
exception = ioex;
}
catch (Exception ex)
{
exception = ex;
}
finally
{
if (exception != null)
{
lyncAgent.Logger.Error( "Error in Conference Migration conf call # " + GetHashCode() + " , Address :" + confSession.ConferenceUri , exception);
}
}
}
Please suggest what could be the possible problem on priority basis.
Thanks in advance.
Does this method reside in an object where it is possible that it will be called by multiple sources at the same time?
If so, using what appears to be a class level variable like _waitForConferenceScheduling could be problematic. Thread A could end up accidentally letting Thread B proceed before Thread B's async action is actually completed. So Thread B could call .BeginEscalate before .EndJoin was called.
When I write UCMA code, I generally use nested callbacks to prevent this type of thing from happening.
Other than that, I'd recommend you run OCSLogger on your application server and the Lync Front End server to gather SIPStack, S3 and Collaboration logs. Looking at the actual SIP messages in detail will provide some clues.
You'd be looking for an INVITE to the conference and the response back to that INVITE.
We managed to detect the reason. It happens if any one in the participant list have already added any contact for meeting in conversation with our endpoint.