Adding nick field to registration new xmpp username using ejabberd - xmpp

I wanted to send "nick" field from client to register new username with ejabberd in band registration. but Server is sending only username, password and instructions fields back to client to fill. I have checked below mod_register to modify these fields but none provide is available.
https://docs.ejabberd.im/admin/configuration/#mod-register
2018-05-29 23:01:08.426 [debug] <0.4613.3>#xmpp_socket:send:218 (tls|<0.4613.3>) Send XML on stream = <<"
<iq xml:lang='en' from='xmpp.test.in' type='result' id='mCbQBXKp-Sd4'>
<query xmlns='jabber:iq:register'>
<username/>
<password/>
<instructions>Choose a username and password to register with this server</instructions>
</query>
</iq>">>
Can any help me how to get nick included in registration itself?

If you are using Smack client for Android you can send additional attributes in createAccount method like:
public void signup(String user, String password, String nickname) throws SmackInvocationException {
connect();
Map<String, String> attributes = new HashMap<String, String>();
attributes.put("name", nickname);
try {
AccountManager.getInstance(con).createAccount(user, password, attributes);
} catch (Exception e) {
throw new SmackInvocationException(e);
}
}
Another approach is to use Vcard with VcardManager and set nickname in smack like (after login or signup):
private Context context;
private XMPPConnection con;
public SmackVCardHelper(Context context, XMPPConnection con) {
this.context = context;
this.con = con;
}
public void save(String nickname) throws SmackInvocationException {
VCard vCard = VCardManager.getInstanceFor(connection).loadVCard();
try {
vCard.setNickName(nickname);
vCard.saveVCard(vcard);
} catch (Exception e) {
throw new SmackInvocationException(e);
}
}

Related

Client to Client notification [duplicate]

I have been trying to read the official docs and guides about how to send message from one device to another. I have saved registration token of both devices in the Real Time Database, thus I have the registration token of another device.
I have tried the following way to send the message
RemoteMessage message = new RemoteMessage.Builder(getRegistrationToken())
.setMessageId(incrementIdAndGet())
.addData("message", "Hello")
.build();
FirebaseMessaging.getInstance().send(message);
However this is not working. The other device doesn't receive any message. I am not even sure, if I can use upstream message sending to conduct device to device communication.
PS: I just want to know if device-to-device messaging is possible using FCM? If yes, then is the code I used have some issue? If yes, then what is the correct way.
Update:
My question was to ask whether device to device messaging without using any separate server other than firebase could messaging is possible or not, if yes than how, since there's no documentation about it. I do not understand what is left to explain here? Anyways I got the answer and will update it as an answer once the question gets reopened.
Firebase has two features to send messages to devices:
the Notifications panel in your Firebase Console allows you to send notifications to specific devices, groups of users, or topics that users subscribed to.
by calling Firebase Cloud Messaging API, you can send messages with whatever targeting strategy you prefer. Calling the FCM API requires access to your Server key, which you should never expose on client devices. That's why you should always run such code on an app server.
The Firebase documentation shows this visually:
Sending messages from one device directly to another device is not supported through the Firebase Cloud Messaging client-side SDKs.
Update: I wrote a blog post detailing how to send notifications between Android devices using Firebase Database, Cloud Messaging and Node.js.
Update 2: You can now also use Cloud Functions for Firebase to send messages securely, without spinning up a server. See this sample use-case to get started. If you don't want to use Cloud Functions, you can run the same logic on any trusted environment you already have, such as your development machine, or a server you control.
Warning There is a very important reason why we don't mention this approach anywhere. This exposes your server key in the APK that
you put on every client device. It can (and thus will) be taken from
there and may lead to abuse of your project. I highly recommend
against taking this approach, except for apps that you only put on
your own devices. – Frank van Puffelen
Ok, so the answer by Frank was correct that Firebase does not natively support device to device messaging. However there's one loophole in that. The Firebase server doesn't identify whether you have send the request from an actual server or are you doing it from your device.
So all you have to do is send a Post Request to Firebase's messaging server along with the Server Key. Just keep this in mind that the server key is not supposed to be on the device, but there's no other option if you want device-to-device messaging using Firebase Messaging.
I am using OkHTTP instead of default way of calling the Rest API. The code is something like this -
public static final String FCM_MESSAGE_URL = "https://fcm.googleapis.com/fcm/send";
OkHttpClient mClient = new OkHttpClient();
public void sendMessage(final JSONArray recipients, final String title, final String body, final String icon, final String message) {
new AsyncTask<String, String, String>() {
#Override
protected String doInBackground(String... params) {
try {
JSONObject root = new JSONObject();
JSONObject notification = new JSONObject();
notification.put("body", body);
notification.put("title", title);
notification.put("icon", icon);
JSONObject data = new JSONObject();
data.put("message", message);
root.put("notification", notification);
root.put("data", data);
root.put("registration_ids", recipients);
String result = postToFCM(root.toString());
Log.d(TAG, "Result: " + result);
return result;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
try {
JSONObject resultJson = new JSONObject(result);
int success, failure;
success = resultJson.getInt("success");
failure = resultJson.getInt("failure");
Toast.makeText(getCurrentActivity(), "Message Success: " + success + "Message Failed: " + failure, Toast.LENGTH_LONG).show();
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getCurrentActivity(), "Message Failed, Unknown error occurred.", Toast.LENGTH_LONG).show();
}
}
}.execute();
}
String postToFCM(String bodyString) throws IOException {
RequestBody body = RequestBody.create(JSON, bodyString);
Request request = new Request.Builder()
.url(FCM_MESSAGE_URL)
.post(body)
.addHeader("Authorization", "key=" + SERVER_KEY)
.build();
Response response = mClient.newCall(request).execute();
return response.body().string();
}
I hope Firebase will come with a better solution in future. But till then, I think this is the only way. The other way would be to send topic message or group messaging. But that was not in the scope of the question.
Update:
The JSONArray is defined like this -
JSONArray regArray = new JSONArray(regIds);
regIds is a String array of registration ids, you want to send this message to. Keep in mind that the registration ids must always be in an array, even if you want it to send to a single recipient.
I have also been using direct device to device gcm messaging in my prototype. It has been working very well. We dont have any server. We exchange GCM reg id using sms/text and then communicate using GCM after that. I am putting here code related to GCM handling
**************Sending GCM Message*************
//Sends gcm message Asynchronously
public class GCM_Sender extends IntentService{
final String API_KEY = "****************************************";
//Empty constructor
public GCM_Sender() {
super("GCM_Sender");
}
//Processes gcm send messages
#Override
protected void onHandleIntent(Intent intent) {
Log.d("Action Service", "GCM_Sender Service Started");
//Get message from intent
String msg = intent.getStringExtra("msg");
msg = "\"" + msg + "\"";
try{
String ControllerRegistrationId = null;
//Check registration id in db
if(RegistrationIdAdapter.getInstance(getApplicationContext()).getRegIds().size() > 0 ) {
String controllerRegIdArray[] = RegistrationIdAdapter.getInstance(getApplicationContext()).getRegIds().get(1);
if(controllerRegIdArray.length>0)
ControllerRegistrationId = controllerRegIdArray[controllerRegIdArray.length-1];
if(!ControllerRegistrationId.equalsIgnoreCase("NULL")){
// 1. URL
URL url = new URL("https://android.googleapis.com/gcm/send");
// 2. Open connection
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// 3. Specify POST method
urlConnection.setRequestMethod("POST");
// 4. Set the headers
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Authorization", "key=" + API_KEY);
urlConnection.setDoOutput(true);
// 5. Add JSON data into POST request body
JSONObject obj = new JSONObject("{\"time_to_live\": 0,\"delay_while_idle\": true,\"data\":{\"message\":" + msg + "},\"registration_ids\":[" + ControllerRegistrationId + "]}");
// 6. Get connection output stream
OutputStreamWriter out = new OutputStreamWriter(urlConnection.getOutputStream());
out.write(obj.toString());
out.close();
// 6. Get the response
int responseCode = urlConnection.getResponseCode();
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null){
response.append(inputLine);
}
in.close();
Log.d("GCM getResponseCode:", new Integer(responseCode).toString());
}else{
Log.d("GCM_Sender:","Field REGISTRATION_TABLE is null");
}
}else {
Log.d("GCM_Sender:","There is no Registration ID in DB ,please sync devices");
}
} catch (Exception e) {
e.printStackTrace();
//MessageSender.getInstance().sendMessage(msg, Commands.SMS_MESSAGE);
}
}
//Called when service is no longer alive
#Override
public void onDestroy() {
super.onDestroy();
//Do a log that GCM_Sender service has been destroyed
Log.d("Action Service", "GCM_Sender Service Destroyed");
}
}
**************Receiving GCM Message*************
public class GCM_Receiver extends WakefulBroadcastReceiver {
public static final String RETRY_ACTION ="com.google.android.c2dm.intent.RETRY";
public static final String REGISTRATION ="com.google.android.c2dm.intent.REGISTRATION";
public SharedPreferences preferences;
//Processes Gcm message .
#Override
public void onReceive(Context context, Intent intent) {
ComponentName comp = new ComponentName(context.getPackageName(),
GCMNotificationIntentService.class.getName());
//Start GCMNotificationIntentService to handle gcm message asynchronously
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
/*//Check if DatabaseService is running .
if(!DatabaseService.isServiceRunning) {
Intent dbService = new Intent(context,DatabaseService.class);
context.startService(dbService);
}*/
//Check if action is RETRY_ACTION ,if it is then do gcm registration again .
if(intent.getAction().equals(RETRY_ACTION)) {
String registrationId = intent.getStringExtra("registration_id");
if(TextUtils.isEmpty(registrationId)){
DeviceRegistrar.getInstance().register(context);
}else {
//Save registration id to prefs .
preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("BLACKBOX_REG_ID",registrationId);
editor.commit();
}
} else if (intent.getAction().equals(REGISTRATION)) {
}
}
}
//Processes gcm messages asynchronously .
public class GCMNotificationIntentService extends IntentService{
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
String gcmData;
private final String TAG = "GCMNotificationIntentService";
//Constructor with super().
public GCMNotificationIntentService() {
super("GcmIntentService");
}
//Called when startService() is called by its Client .
//Processes gcm messages .
#Override
protected void onHandleIntent(Intent intent) {
Log.d("GCMNotificationIntentService", "GCMNotificationIntentService Started");
Bundle extras = intent.getExtras();
//Get instance of GoogleCloudMessaging .
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
//Get gcm message type .
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) {
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
.equals(messageType)) {
sendNotification("Send error: " + extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
.equals(messageType)) {
sendNotification("Deleted messages on server: "
+ extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
.equals(messageType)) {
Log.i(TAG, "Completed work # " + SystemClock.elapsedRealtime());
gcmData = extras.getString("message");
Intent actionService = new Intent(getApplicationContext(),Action.class);
actionService.putExtra("data", gcmData);
//start Action service .
startService(actionService);
//Show push notification .
sendNotification("Action: " + gcmData);
//Process received gcmData.
Log.d(TAG,"Received Gcm Message from Controller : " + extras.getString("message"));
}
}
GCM_Receiver.completeWakefulIntent(intent);
}
//Shows notification on device notification bar .
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(this, BlackboxStarter.class);
//Clicking on GCM notification add new layer of app.
notificationIntent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this).setSmallIcon(R.drawable.gcm_cloud)
.setContentTitle("Notification from Controller")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
//Play default notification
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
} catch (Exception e) {
e.printStackTrace();
}
}
//Called when service is no longer be available .
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d("GCMNotificationIntentService", "GCMNotificationIntentService Destroyed");
}
}
According to the new documentation which was updated on October 2, 2018 you must send post request as below
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA //Server key
{
"to": "sent device's registration token",
"data": {
"hello": "message from someone",
}
}
To get device's registration token extend FirebaseMessagingService and override onNewToken(String token)
For more info refer to doc https://firebase.google.com/docs/cloud-messaging/android/device-group
I am late but above solutions has helped me to write down this simple answer, you can send your message directly to android devices from android application, here is the simple implementation I have done and it works great for me.
compile android volley library
compile 'com.android.volley:volley:1.0.0'
Just copy paste this simple function ;) and your life will become smooth just like knife in butter. :D
public static void sendPushToSingleInstance(final Context activity, final HashMap dataValue /*your data from the activity*/, final String instanceIdToken /*firebase instance token you will find in documentation that how to get this*/ ) {
final String url = "https://fcm.googleapis.com/fcm/send";
StringRequest myReq = new StringRequest(Request.Method.POST,url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(activity, "Bingo Success", Toast.LENGTH_SHORT).show();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(activity, "Oops error", Toast.LENGTH_SHORT).show();
}
}) {
#Override
public byte[] getBody() throws com.android.volley.AuthFailureError {
Map<String, Object> rawParameters = new Hashtable();
rawParameters.put("data", new JSONObject(dataValue));
rawParameters.put("to", instanceIdToken);
return new JSONObject(rawParameters).toString().getBytes();
};
public String getBodyContentType()
{
return "application/json; charset=utf-8";
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Authorization", "key="+YOUR_LEGACY_SERVER_KEY_FROM_FIREBASE_CONSOLE);
headers.put("Content-Type","application/json");
return headers;
}
};
Volley.newRequestQueue(activity).add(myReq);
}
Note
If you want to send message to topics so you can change parameter instanceIdToken to something like /topics/topicName.
For groups implementation is the same but you just need to take care of parameters. checkout Firebase documentation and you can pass those parameters.
let me know if you face any issue.

Created sendgrid email template, how to call it from Java

I have created email template in sendgrid - with substitutable values;
I get the JSON payload (contains substitute values) for processing email from rabbitMQ queue. My question is how to call the sendgrid email template from Java?
I found the solution, the way to call sendgrid template and email through sendgrid as below:
SendGrid sendGrid = new SendGrid("username","password"));
SendGrid.Email email = new SendGrid.Email();
//Fill the required fields of email
email.setTo(new String[] { "xyz_to#gmail.com"});
email.setFrom("xyz_from#gmail.com");
email.setSubject(" ");
email.setText(" ");
email.setHtml(" ");
// Substitute template ID
email.addFilter(
"templates",
"template_id",
"1231_1212_2323_3232");
//place holders in template, dynamically fill values in template
email.addSubstitution(
":firstName",
new String[] { firstName });
email.addSubstitution(
":lastName",
new String[] { lastName });
// send your email
Response response = sendGrid.send(email);
This is my working soloution .
import com.fasterxml.jackson.annotation.JsonProperty;
import com.sendgrid.*;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class MailUtil {
public static void main(String[] args) throws IOException {
Email from = new Email();
from.setEmail("fromEmail");
from.setName("Samay");
String subject = "Sending with SendGrid is Fun";
Email to = new Email();
to.setName("Sam");
to.setEmail("ToEmail");
DynamicTemplatePersonalization personalization = new DynamicTemplatePersonalization();
personalization.addTo(to);
Mail mail = new Mail();
mail.setFrom(from);
personalization.addDynamicTemplateData("name", "Sam");
mail.addPersonalization(personalization);
mail.setTemplateId("TEMPLATE-ID");
SendGrid sg = new SendGrid("API-KEY");
Request request = new Request();
try {
request.setMethod(Method.POST);
request.setEndpoint("mail/send");
request.setBody(mail.build());
Response response = sg.api(request);
System.out.println(response.getStatusCode());
System.out.println(response.getBody());
System.out.println(response.getHeaders());
} catch (IOException ex) {
throw ex;
}
}
private static class DynamicTemplatePersonalization extends Personalization {
#JsonProperty(value = "dynamic_template_data")
private Map<String, String> dynamic_template_data;
#JsonProperty("dynamic_template_data")
public Map<String, String> getDynamicTemplateData() {
if (dynamic_template_data == null) {
return Collections.<String, String>emptyMap();
}
return dynamic_template_data;
}
public void addDynamicTemplateData(String key, String value) {
if (dynamic_template_data == null) {
dynamic_template_data = new HashMap<String, String>();
dynamic_template_data.put(key, value);
} else {
dynamic_template_data.put(key, value);
}
}
}
}
Here is an example from last API spec:
import com.sendgrid.*;
import java.io.IOException;
public class Example {
public static void main(String[] args) throws IOException {
Email from = new Email("test#example.com");
String subject = "I'm replacing the subject tag";
Email to = new Email("test#example.com");
Content content = new Content("text/html", "I'm replacing the <strong>body tag</strong>");
Mail mail = new Mail(from, subject, to, content);
mail.personalization.get(0).addSubstitution("-name-", "Example User");
mail.personalization.get(0).addSubstitution("-city-", "Denver");
mail.setTemplateId("13b8f94f-bcae-4ec6-b752-70d6cb59f932");
SendGrid sg = new SendGrid(System.getenv("SENDGRID_API_KEY"));
Request request = new Request();
try {
request.setMethod(Method.POST);
request.setEndpoint("mail/send");
request.setBody(mail.build());
Response response = sg.api(request);
System.out.println(response.getStatusCode());
System.out.println(response.getBody());
System.out.println(response.getHeaders());
} catch (IOException ex) {
throw ex;
}
}
}
https://github.com/sendgrid/sendgrid-java/blob/master/USE_CASES.md
Recently Sendgrid upgraded the Maven version v4.3.0 so you don't have to create additional classes for dynamic data content. Read more from this link https://github.com/sendgrid/sendgrid-java/pull/449
If you're doing a spring-boot maven project, You'll need to add the sendgrid-java maven dependency in your pom.xml. Likewise, in your application.properties file under resource folder of the project, add SENDGRID API KEY AND TEMPLATE ID under attributes such as spring.sendgrid.api-key=SG.xyz and templateId=d-cabc respectively.
Having done the pre-setups. You can create a simple controller class as the one given below:
Happy Coding!
#RestController
#RequestMapping("/sendgrid")
public class MailResource {
private final SendGrid sendGrid;
#Value("${templateId}")
private String EMAIL_TEMPLATE_ID;
public MailResource(SendGrid sendGrid) {
this.sendGrid = sendGrid;
}
#GetMapping("/test")
public String sendEmailWithSendGrid(#RequestParam("msg") String message) {
Email from = new Email("bijay.shrestha#f1soft.com");
String subject = "Welcome Fonesal Unit to SendGrid";
Email to = new Email("birat.bohora#f1soft.com");
Content content = new Content("text/html", message);
Mail mail = new Mail(from, subject, to, content);
mail.setReplyTo(new Email("bijay.shrestha#f1soft.com"));
mail.setTemplateId(EMAIL_TEMPLATE_ID);
Request request = new Request();
Response response = null;
try {
request.setMethod(Method.POST);
request.setEndpoint("mail/send");
request.setBody(mail.build());
response = sendGrid.api(request);
System.out.println(response.getStatusCode());
System.out.println(response.getBody());
System.out.println(response.getHeaders());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
return "Email was successfully sent";
}
}
This is based on verision com.sendgrid:sendgrid-java:4.8.3
Email from = new Email(fromEmail);
Email to = new Email(toEmail);
String subject = "subject";
Content content = new Content(TEXT_HTML, "dummy value");
Mail mail = new Mail(from, subject, to, content);
// Using template to send Email, so subject and content will be ignored
mail.setTemplateId(request.getTemplateId());
SendGrid sendGrid = new SendGrid(SEND_GRID_API_KEY);
Request sendRequest = new Request();
sendRequest.setMethod(Method.POST);
sendRequest.setEndpoint("mail/send");
sendRequest.setBody(mail.build());
Response response = sendGrid.api(sendRequest);
You can also find fully example here:
Full Email object Java example

How to register new user without need to login?

I have problem with registering new user on my OpenFire server. This is a reply from server.
<iq id='XILKN-9' to='pc-pc/b529612d' from='192.168.21.107' type='error'>
<query xmlns='jabber:iq:register'>
<password>123</password>
<email>bear#bear.com</email>
<username>bear</username>
</query>
<error type="modify">
<bad-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error>
</iq>
But when I login with any existing user before registering new user, I can register new user successfully and this is the reply from server
<iq id='XILKN-15' to='kkk#pc-pc/Smack' from='pc-pc' type='result'></iq>
Here is my code :
String user ="bear";
String pass = "123";
String email = "bear#bear.com";
HashMap<String,String> attr = new HashMap<String, String>();
attr.put("username",user);
attr.put("password",pass);
attr.put("email", email);
if(conn2!=null) {
Registration reg = new Registration();
reg.setType(IQ.Type.SET);
reg.setTo(conn2.getServiceName());
reg.setAttributes(attr);
PacketFilter filter = new AndFilter(new PacketIDFilter(
reg.getPacketID()), new PacketTypeFilter(IQ.class));
PacketCollector collector = conn2 .createPacketCollector(filter);
try {
conn2.sendPacket(reg);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
IQ result = (IQ) collector.nextResult(SmackConfiguration
.getDefaultPacketReplyTimeout());
System.out.println(result);
collector.cancel();
I used OpenFire 3.9.3 and aSmack 4.0.7 .
If I understand you correct I solve this issue by the next steps.
creat connection with the server.
then you use with AccountManager
then you create new account by createAccount
So with should be something like that:
AccountManager am = connection.getAccountManager();
Map<String, String> attributes = new HashMap<String, String>();
attributes.put("username", username);
attributes.put("password", password);
attributes.put("email", email);
attributes.put("name", name);
try {
am.createAccount(username, password,attributes);
Toast.makeText(getActivity(),"User create: " + username,Toast.LENGTH_SHORT).show();
} catch (XMPPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

How use SocialAuth with JSF to redirect?

I'm trying to use SocialAuth, the idea is very simple, click in log in with facebook then redirect the user to my website signed in.
The log in part I get it, which is below :
1) /index.xhtml
<h:form id="login-facebook">
<h:commandButton id="login" action="#{socialFacebook.login}" value="Login"/>
</h:form>
2) socialFacebook bean
package controller;
#ManagedBean(name="socialFacebook")
#RequestScoped
public class SocialFacebook implements Serializable{
private static final long serialVersionUID = -4787254243136316495L;
private String code;
#PostConstruct
public void init(){
try {
HttpServletRequest request=(HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
SocialAuthManager manager = (SocialAuthManager)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("authManager");
Map<String, String> paramsMap = SocialAuthUtil.getRequestParametersMap(request);
AuthProvider provider = manager.connect(paramsMap);
// get profile
Profile p = provider.getUserProfile();
System.out.println(p.getFullName());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void login(){
try {
HttpServletRequest request=(HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
//Create an instance of SocialAuthConfig object
SocialAuthConfig config = SocialAuthConfig.getDefault();
//load configuration. By default load the configuration from oauth_consumer.properties.
//You can also pass input stream, properties object or properties file name.
config.load();
//Create an instance of SocialAuthManager and set config
SocialAuthManager manager = new SocialAuthManager();
manager.setSocialAuthConfig(config);
//URL of YOUR application which will be called after authentication
//String successUrl = "http://localhost:8080/cc/pages/system/login_facebook.xhtml" + ";jsessionid=" + req.getSession().getId();
String successUrl = "http://localhost:8080/cc/pages/system/index.xhtml" + ";jsessionid=" + request.getSession().getId();
// get Provider URL to which you should redirect for authentication.
// id can have values "facebook", "twitter", "yahoo" etc. or the OpenID URL
String url = manager.getAuthenticationUrl("facebook", successUrl);
// Store in session
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("authManager", manager);
//redirect to the successful login page
FacesContext.getCurrentInstance().responseComplete();
FacesContext.getCurrentInstance().getExternalContext().redirect(url);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
3) Facebook returned the following URL:
http://localhost:8080/cc/pages/system/home_facebook.xhtml;jsessionid=e143aa975fa3f313c677fbcb03e3?code=AQAmJXdQX0B__zJHXnRyPfgaG1CfNUEEEEEEEEEEEEEEEZJLEpsT5s1spd3KtWGWI2HYaIOZKLkrn8axKs4iKwJVQJwJQB_WSs2iWkp2DDDDDDDDDDDDtdRPLPG7psp6r2PYmn7CTm2QNNha7f1QlgmoZtBsIEF0SSSSSSSSSSSSSSSSSSSSSSS8RutAU8dqI2KDE57f#_=_
4) It pass by my init method as BalusC suggest but always prints nope :( :
#ManagedBean(name="redirectFacebook")
#RequestScoped
public class RedirectFacebook implements Serializable{
private static final long serialVersionUID = -566276017320074630L;
private String code;
private Profile profile;
#PostConstruct
public void init(){
try {
HttpServletRequest request=(HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpSession session = (HttpSession) request.getAttribute("jsessionid");
if (request.getAttribute("code") != null)
System.out.println("code");
else
System.out.println("nope :(");
if (session != null){
SocialAuthManager manager = (SocialAuthManager)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("authManager");
Map<String, String> paramsMap = SocialAuthUtil.getRequestParametersMap(request);
AuthProvider provider = manager.connect(paramsMap);
// get profile
profile = provider.getUserProfile();
System.out.println(profile.getFullName());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
5) And it prints nope :( too in my home_facebook page:
<h:form id="redirect-facebook-form">
<f:metadata>
<f:viewParam name="code" value="#{redirectFacebook.code}" />
</f:metadata>
<h:panelGroup rendered="#{not empty redirectFacebook.profile}">
Hello, you're successfully associated as #{socialFacebook.profile.firstName} on Facebook
</h:panelGroup>
<h:panelGroup rendered="#{empty redirectFacebook.profile}">
Nope :(
</h:panelGroup>
</h:form>
But, I'm a bit confuse how to get the result in my bean and do some verifications as if the user is registered or not for instance. I know, looking some code in Google, that I have to do this, but how can I redirect to my bean and do this and redirect the user to the proper page ?
SocialAuthManager manager = (SocialAuthManager)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("authManager");
Map<String, String> paramsMap = SocialAuthUtil.getRequestParametersMap(request);
AuthProvider provider = manager.connect(paramsMap);
// get profile
Profile p;
p = provider.getUserProfile();
This is really taking some nights to figure it out.
Any idea is very appreaciated, thanks.
I don't see any code level issue except you are using localhost in URL.
Here is a wiki link which describes how to run application with localhost.
Please let me know if this does not work.

XMPP: Smack client not receiving chat message

I've been struggling with XMPP chatting a lot through Smack and Openfire server.
My problem is as follows:
Whenever a user sends a message to another user, the message is received correctly at the other user. But any reply doesn't show up at the sender of the first message.
So User 1 sends to User 2 successfully. User 2 is then unable to send to User 1 any reply.
On the other hand, if I restart and let the users login again, User 2 can send to User 1 but not vice versa.
What I'm trying to say is that only the initiator of the chat can send a message, the receiver cannot reply back.
My code looks like this
package xmpp;
public class XMPPClient{
private static final int packetReplyTimeout = 500; // millis
private XMPPConnection connection;
private ChatManager chatManager;
private MessageListener messageListener;
private ConnectionConfiguration config;
private MyTimer t = MyTimer.getInstance();
private ArrayList<String> threadPool = new ArrayList<String>();
public XMPPClient()
{
SmackConfiguration.setPacketReplyTimeout(packetReplyTimeout);
//define openfire server information
config = new ConnectionConfiguration("localhost",5222);
config.setSASLAuthenticationEnabled(false);
config.setSecurityMode(SecurityMode.disabled);
connection = new XMPPConnection(config);
//connect to server
t.start("Connecting to server...");
try {
connection.connect();
} catch (XMPPException e) {
System.err.println("Failed to connect to server! Connect to VPN!\t"+e.getMessage());
System.exit(0);
}
t.end("Connection took ");
//setup chat mechanism
chatManager = connection.getChatManager();
chatManager.addChatListener(
new ChatManagerListener() {
#Override
public void chatCreated(Chat chat, boolean createdLocally)
{
if (!createdLocally)
chat.addMessageListener(new MyMessageListener());
}
});
}
public boolean login(String userName, String password, String resource) {
t.start("Logging in...");
try {
if (connection!=null && connection.isConnected())
connection.login(userName, password, resource);
//set available presence
setStatus(true);
}
catch (XMPPException e) {
if(e.getMessage().contains("auth")){
System.err.println("Invalid Login Information!\t"+e.getMessage());
}
else{
e.printStackTrace();
}
return false;
}
t.end("Logging in took ");
return true;
}
public void setStatus(boolean available) {
if(available)
connection.sendPacket(new Presence(Presence.Type.available));
else
connection.sendPacket(new Presence(Presence.Type.unavailable));
}
public void sendMessage(String message, String buddyJID) throws XMPPException {
System.out.println(String.format("Sending mesage '%1$s' to user %2$s", message, buddyJID));
boolean chatExists = false;
Chat c = null;
for(String tid : threadPool)
{
if((c = chatManager.getThreadChat(tid)) != null)
{
if(c.getParticipant().equals(buddyJID))
{
if(checkAvailability(buddyJID))
{
chatExists = true;
break;
}
else
{
threadPool.remove(tid);
break;
}
}
}
}
if (chatExists)
{
Chat chat = c;
chat.sendMessage(message);
}
else
{
Chat chat = chatManager.createChat(buddyJID, messageListener);
threadPool.add(chat.getThreadID()); System.out.println(chat.getThreadID());
chat.sendMessage(message);
}
}
public void createEntry(String user, String name) throws Exception {
System.out.println(String.format("Creating entry for buddy '%1$s' with name %2$s", user, name));
Roster roster = connection.getRoster();
roster.createEntry(user, name, null);
}
public boolean checkAvailability(String jid)
{
System.out.print("Checking availability for: "+jid+"=");
System.out.println(connection.getRoster().getPresence(jid).isAvailable());
return connection.getRoster().getPresence(jid).isAvailable();
}
public void disconnect() {
if (connection!=null && connection.isConnected()) {
setStatus(false);
connection.disconnect();
}
}
}
import org.jivesoftware.smack.packet.Message;
public class MyMessageListener implements MessageListener {
#Override
public void processMessage(Chat chat, Message message) {
String from = message.getFrom();
String body = message.getBody();
System.out.println(String.format("Received message '%1$s' from %2$s", body, from));
}
}
I'm not sure what the problem is. Any suggestions? Sample code?
Thanks <3
I am not sure if this will help you but I can get reply with this code:
public void chat(String AddressedUser) throws NotConnectedException {
//Create username whom we want to send a message
String userToSend = AddressedUser + "#" + serverDomain;
ChatManager chatmanager = ChatManager.getInstanceFor(connection);
Chat newChat = chatmanager.createChat(userToSend , new MessageListener() {
#Override
public void processMessage(Chat chat, Message message ) {
// TODO Auto-generated method stub
System.out.println("Received message: " + message);
}
});
try {
newChat.sendMessage("Hey");
}
catch (XMPPException e) {
System.out.println("Error Delivering block");
}
}
I am sending "Hey" then what ever other user writes I will see in my logcat.
You haven't specified what the receiver is, for instance, if it is an existing client (like Spark for instance), or more custom code. This would be helpful, as would knowing what version of Smack you are using.
That particular code has several issues with it.
It keeps creating new Chat objects for every message sent, instead of
simply reusing the same chat.
There is no ChatManagerListener registered to handle new Chat messages that are not tied to an existing chat.
the is code is very complicated and it seems is meant only to send msgs.
Here is a sample code that works perfectly, both sending and receiving:
http://www.javaprogrammingforums.com/java-networking-tutorials/551-how-write-simple-xmpp-jabber-client-using-smack-api.html