I am trying to import a class of a jar file.
I am able to import every class except one.
Here you can see the jar which contains all the classes I would like to import:
Here you can see the import, missing the HexoskinHTTPClient class:
The class itself looks as follows:
package com.companyname.hexoskin;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.companyname.hexoskin.models.HexoskinDataPoint;
import com.companyname.hexoskin.models.HexoskinRecord;
import com.companyname.hexoskin.models.HexoskinDatatype;
import com.companyname.hexoskin.models.HexoskinUnit;
import kong.unirest.Unirest;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.DecimalFormat;
import java.util.*;
class HexoskinHTTPClient {
private String host;
private String[] incompatibleDatatypes = {"8192", "8193", "8194", "1019", "54", "215", "281", "282", "283", "1053", "1049"};
/**
* Constructor
* #param host: The url of the API
*/
HexoskinHTTPClient(String host) {
this.host = host;
}
/**
* https://api.hexoskin.com/docs/resource/record
* #return ArrayList: List of records of type HexoskinRecord
* #throws IOException
*/
ArrayList<HexoskinRecord> getRecordsWithoutDetails() throws IOException {
// Fetch records
String response = Unirest.get(this.host + "record" + "?limit=0")
.basicAuth(HexoskinCredentials.user, HexoskinCredentials.password)
.asString()
.getBody();
// Get records array from response
ObjectMapper objectMapper = new ObjectMapper();
JsonNode records = objectMapper.readTree(response).get("objects");
// Extract relevant properties and create object
ArrayList<HexoskinRecord> hexoskinRecords = new ArrayList<>();
for(int i = 0; i < records.size(); i++) {
HexoskinRecord hexoskinRecord = objectMapper.readValue(records.get(i).toString(), HexoskinRecord.class);
hexoskinRecords.add(hexoskinRecord);
}
return hexoskinRecords;
}
/**
* https://api.hexoskin.com/docs/resource/datatype
* #return ArrayList: List of datatypes of type HexoskinDatatype
* #throws IOException
*/
ArrayList<HexoskinDatatype> getDatatypes() throws IOException, URISyntaxException {
// Fetch records
String response = Unirest.get(this.host + "datatype?limit=0")
.basicAuth(HexoskinCredentials.user, HexoskinCredentials.password)
.asString()
.getBody();
// Get datatypes array from response
ObjectMapper objectMapper = new ObjectMapper();
JsonNode datatypes = objectMapper.readTree(response).get("objects");
// Convert String Array to List
List<String> incompatibleDatatypesAsList = Arrays.asList(incompatibleDatatypes);
// Extract relevant properties and create object
ArrayList<HexoskinDatatype> hexoskinDatatypes = new ArrayList<>();
for(int i = 0; i < datatypes.size(); i++) {
// filter out incompatible types
if (!incompatibleDatatypesAsList.contains(datatypes.get(i).get("id").toString())) {
HexoskinDatatype hexoskinDatatype = objectMapper.readValue(datatypes.get(i).toString(), HexoskinDatatype.class);
// Get the unit id from unit uri
URI uri = new URI(hexoskinDatatype.getUnit());
String[] segments = uri.getPath().split("/");
String id = segments[segments.length - 1];
// Create the unit object
HexoskinUnit hexoskinUnit = this.getUnit(id);
hexoskinDatatype.setUnitObject(hexoskinUnit);
hexoskinDatatypes.add(hexoskinDatatype);
}
}
return hexoskinDatatypes;
}
/**
* https://api.hexoskin.com/docs/resource/unit
* #param unitToFetch: The id of the unit of which data should be fetched
* #return Hashmap: Map of units of type HexoskinUnit
* #throws IOException
*/
HexoskinUnit getUnit(String unitToFetch) throws IOException {
// Fetch records
String response = Unirest.get(this.host + "unit/" + unitToFetch)
.basicAuth(HexoskinCredentials.user, HexoskinCredentials.password)
.asString()
.getBody();
// Get unit from response
ObjectMapper objectMapper = new ObjectMapper();
JsonNode unit = objectMapper.readTree(response);
HexoskinUnit hexoskinUnit = objectMapper.readValue(unit.toString(), HexoskinUnit.class);
return hexoskinUnit;
}
/**
* https://api.hexoskin.com/docs/resource/data/
* #param recordId: The id of the record of which data should be fetched
* #param datatypes: The datatypes to fetch
* #return ArrayList: List of datapoints of type HexoskinDataPoint
* #throws IOException
*/
ArrayList<HexoskinDataPoint> getRecord(String recordId, ArrayList<HexoskinDatatype> datatypes) throws IOException {
String datatypesList = "";
for(int i = 0; i < datatypes.size(); i++) {
datatypesList += datatypes.get(i).getId();
if (i < datatypes.size() - 1) {
datatypesList += ",";
}
}
String response = Unirest.get(this.host + "data?datatype__in=" + datatypesList + "&record=" + recordId + "&limit=0")
.basicAuth(HexoskinCredentials.user, HexoskinCredentials.password)
.asString()
.getBody();
// Get data array from response
ObjectMapper objectMapper = new ObjectMapper();
JsonNode dataPointWrappers = objectMapper.readTree(response).get(0).get("data");
// Extract relevant properties and create object
ArrayList<HexoskinDataPoint> hexoskinDataPoints = new ArrayList<>();
for(int i = 0; i < datatypes.size(); i++) {
JsonNode dataPointWrapper = dataPointWrappers.get(datatypes.get(i).getId());
// Only create data points for entries with subentries
if (dataPointWrapper != null && dataPointWrapper.size() != 0) {
for(int j = 0; j < dataPointWrapper.size(); j++) {
HexoskinDataPoint hexoskinDataPoint = new HexoskinDataPoint(datatypes.get(i).getId());
if (dataPointWrapper.get(j).get(0) != null && !dataPointWrapper.get(j).get(0).toString().equals("null")) {
// Remove decimals which cause scientific notation strings
double secondNumber = Double.parseDouble(dataPointWrapper.get(j).get(0).toString());
DecimalFormat decimalFormat = new DecimalFormat("0");
String timestamp = decimalFormat.format(secondNumber);
hexoskinDataPoint.setTimestamp(timestamp);
} else {
hexoskinDataPoint.setTimestamp("NA");
}
if (dataPointWrapper.get(j).get(1) != null && !dataPointWrapper.get(j).get(1).toString().equals("null")) {
hexoskinDataPoint.setValue(dataPointWrapper.get(j).get(1).toString());
} else {
hexoskinDataPoint.setValue("NA");
}
hexoskinDataPoints.add(hexoskinDataPoint);
}
}
}
return hexoskinDataPoints;
}
/**
* Unirest starts a background event loop and your Java application won’t be able to exit
* until you manually shutdown all the threads.
*/
void destroy() {
Unirest.shutDown();
}
}
Do you have any idea why exactly one class (HexoskinHTTPClient) cannot be found?
As per my understanding "HexoskinHTTPClient" is not public class, this class declared with default package modified that's why this class not visible outside of package. make the class public i think it will work.
So, Google used to have a nice page where they gave code sample on how to implement a GCM Xmpp server on this page:
https://developers.google.com/cloud-messaging/ccs
I had bookmarked this answer anytime I wanted to view the implementation
Confused about Google GCM XMPP
But everything linked from in that answer is gone. Google deleted them.
But now, they have removed everything, and added a page that just explains what it does. Sure, but the sample java code would be nice. I tried to go to the sample site on github that they link to
https://github.com/google/gcm
but it only provides samples of HTTP GCM server version.
Can somebody point me to a working code sample please? Or Is there a library out there that would work with c# at all? if not, I would just settle with the java version too.
Thanks.
Here is one I wrote for a class example (with some non-XMPP parts deleted to keep it small enough so I can post the code, but have the full server at http://people.eku.edu/styere/GcmPushServer.java):
// derived from https://developer.android.com/google/gcm/ccs.html
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
//import javax.swing.JScrollPane;
//import javax.swing.SwingUtilities;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketInterceptor;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.DefaultPacketExtension;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.util.StringUtils;
import org.json.simple.JSONValue;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
import org.xmlpull.v1.XmlPullParser;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Random;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.HttpsURLConnection;
// list of all users and associated devices
class UserList {
// (--deleted--)
// constructor/read existing data from file
public UserList() {
// (--deleted--)
}
// add a new device to an existing user (called from networking thread)
// duplicate IDs are quietly accepted
public synchronized void addDevice( String uname, String newRegToken ) {
// (--deleted--)
}
// generate a group address/notification key
// !!!!!!!!!!!!!!! W A R N I N G !!!!!!!!!!!!!!!
// If the group addr/notification key is lost, it currently CANNOT be recovered/rebuilt
public String createNotificationKey( String nKeyName, String addr ) {
String[] idset = new String[1];
idset[0] = addr;
String newGroupAddr;
try {
// create a https connection to create the notification_key
URL url = new URL( "https://android.googleapis.com/gcm/notification" );
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
// send as a POST request
conn.setRequestMethod("POST");
// add request parameters
conn.addRequestProperty( "project_id", ""+GcmPushServer.senderId );
conn.addRequestProperty( "Authorization", "key="+GcmPushServer.password );
// use "set" since this may already exist
conn.setRequestProperty( "Content-Type", "application/json" );
// create data to send with request
Map<String,Object> sendData = new HashMap<>();
// create a new notification key
sendData.put( "operation", "create" );
sendData.put( "notification_key_name", (--deleted--) );
sendData.put( "registration_ids", (--deleted--) );
String strData = JSONValue.toJSONString(sendData);
// Send post request
conn.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes( strData );
wr.flush();
wr.close();
// successful?
int rc = conn.getResponseCode();
//System.out.println("ResponseCode = " + rc );
// read the response
Scanner input = new Scanner( conn.getInputStream() );
String resp="";
// read/display lines
while( input.hasNextLine() ) {
String s = input.nextLine();
resp += s;
}
//System.out.println("Response content: " + resp);
if ( rc == HttpsURLConnection.HTTP_OK ) {
JSONObject obj = (JSONObject) JSONValue.parse(resp);
newGroupAddr = (String) obj.get( "notification_key" );
//System.out.println(" new notification_key: " + newGroupAddr );
return newGroupAddr;
} else {
}
} catch ( Exception e ) {
//System.out.println("-- Exception: " + e.getMessage() );
}
return null;
}
// add/delete a single address to/from a notification key
// (add if doAdd is true, delete otherwise)
// removing final address will quietly delete the key
public static void modifyNotificationKey( String nKeyName, String nKey,
String addr, boolean doAdd ) {
String[] idset = new String[1];
idset[0] = addr;
try {
// create a https connection to create the notification_key
URL url = new URL( "https://android.googleapis.com/gcm/notification" );
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
// send as a POST request
conn.setRequestMethod("POST");
// add request parameters
conn.addRequestProperty( "project_id", ""+GcmPushServer.senderId );
conn.addRequestProperty( "Authorization", "key="+GcmPushServer.password );
// use "set" since this may already exist
conn.setRequestProperty( "Content-Type", "application/json" );
// create data to send with request
Map<String,Object> sendData = new HashMap<>();
// create a new notification key
sendData.put( "operation", doAdd? "add" : "remove" ); // add or delete key?
sendData.put( "notification_key_name", (--deleted--) );
sendData.put( "notification_key", (--deleted--) );
sendData.put( "registration_ids", (--deleted--) );
String strData = JSONValue.toJSONString(sendData);
//System.out.println("genGroupAddress POST data: " + strData );
// Send post request
conn.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes( strData );
wr.flush();
wr.close();
//conn.openConnection();
// successful?
int rc = conn.getResponseCode();
//System.out.println("ResponseCode = " + rc );
Scanner input = new Scanner( conn.getInputStream() );
// read/display lines
while( input.hasNextLine() ) {
System.out.println("Response content:");
String s = input.nextLine();
System.out.println( s );
}
} catch ( Exception e ) {
// do nothing
}
}
}
// text area for log messages
class LogTextArea extends JTextArea {
// update the "log" with the specified message
public void logMessage( String msg ) {
// (--deleted--)
}
}
class CcsServer {
private static final String GCM_SERVER = "gcm.googleapis.com";
private static final int GCM_PORT = 5235;
private static final String GCM_ELEMENT_NAME = "gcm";
private static final String GCM_NAMESPACE = "google:mobile:data";
// display/log area
LogTextArea logArea;
UserList users;
CcsServer( LogTextArea lta, UserList u ) {
logArea = lta;
users = u;
}
static {
ProviderManager.addExtensionProvider(GCM_ELEMENT_NAME, GCM_NAMESPACE,
new PacketExtensionProvider() {
#Override
public PacketExtension parseExtension(XmlPullParser parser) throws
Exception {
String json = parser.nextText();
return new GcmPacketExtension(json);
}
});
}
private XMPPConnection connection;
/**
* Indicates whether the connection is in draining state, which means that it
* will not accept any new downstream messages.
*/
protected volatile boolean connectionDraining = false;
/**
* Sends a downstream message to GCM.
*
* #return true if the message has been successfully sent.
*/
public boolean sendDownstreamMessage(String jsonRequest) throws
NotConnectedException {
if (!connectionDraining) {
send(jsonRequest);
return true;
}
logArea.logMessage("Dropping downstream message since the connection is draining");
return false;
}
/**
* Returns a random message id to uniquely identify a message.
*
* <p>Note: This is generated by a pseudo random number generator for
* illustration purpose, and is not guaranteed to be unique.
*/
public String nextMessageId() {
return "m-" + UUID.randomUUID().toString();
}
/**
* Sends a packet with contents provided.
*/
protected void send(String jsonRequest) throws NotConnectedException {
Packet request = new GcmPacketExtension(jsonRequest).toPacket();
connection.sendPacket(request);
}
/**
* Handles an upstream data message from a device application.
*
* <p>This sample echo server sends an echo message back to the device.
* Subclasses should override this method to properly process upstream messages.
*/
protected void handleUpstreamMessage(Map<String, Object> jsonObject) {
// PackageName of the application that sent this message.
String category = (String) jsonObject.get("category");
String from = (String) jsonObject.get("from");
#SuppressWarnings("unchecked")
Map<String, String> payload = (Map<String, String>) jsonObject.get("data");
// what type of upstream message is this?
if ( ! payload.containsKey( "my_action" ) )
{
// Hmmm - this shouldn't happen!
logArea.logMessage( "handleUpstreamMessage - incoming message is missing my_action" );
// just ignore the message
return;
}
// what action do they want?
String my_action = (String) payload.get( "my_action" );
if ( my_action.equals( "edu.eku.styere.gcmpushclient.REGISTER" ) ) {
// registration request
String username = (String) payload.get( "username" );
logArea.logMessage( "Registration request: user=" + username + ", ID/Token=" + from );
// save the information
users.addDevice( username, from );
return;
} else {
// take default action of echoing the message
payload.put("ECHO", "Application: " + category);
// Send an ECHO response back
String echo = createJsonMessage(from, nextMessageId(), payload,
"echo:CollapseKey", null, false);
try {
sendDownstreamMessage(echo);
} catch (NotConnectedException e) {
logArea.logMessage( "Not connected anymore, echo message is not sent: " + e.getMessage() );
}
}
}
/**
* Handles an ACK.
*
* <p>Logs a INFO message, but subclasses could override it to
* properly handle ACKs.
*/
protected void handleAckReceipt(Map<String, Object> jsonObject) {
String messageId = (String) jsonObject.get("message_id");
String from = (String) jsonObject.get("from");
logArea.logMessage( "handleAckReceipt() from: " + from + ", messageId: " + messageId );
}
/**
* Handles a NACK.
*
* <p>Logs a INFO message, but subclasses could override it to
* properly handle NACKs.
*/
protected void handleNackReceipt(Map<String, Object> jsonObject) {
String messageId = (String) jsonObject.get("message_id");
String from = (String) jsonObject.get("from");
logArea.logMessage( "handleNackReceipt() from: " + from + ", messageId: " + messageId );
}
protected void handleControlMessage(Map<String, Object> jsonObject) {
logArea.logMessage( "handleControlMessage(): " + jsonObject );
String controlType = (String) jsonObject.get("control_type");
if ("CONNECTION_DRAINING".equals(controlType)) {
connectionDraining = true;
} else {
logArea.logMessage( "Unrecognised control type: " + controlType + ". This could "+
"happen if new features are " + "added to the CCS protocol." );
}
}
/**
* Creates a JSON encoded GCM message.
*
* #param to RegistrationId of the target device (Required).
* #param messageId Unique messageId for which CCS sends an
* "ack/nack" (Required).
* #param payload Message content intended for the application. (Optional).
* #param collapseKey GCM collapse_key parameter (Optional).
* #param timeToLive GCM time_to_live parameter (Optional).
* #param delayWhileIdle GCM delay_while_idle parameter (Optional).
* #return JSON encoded GCM message.
*/
public static String createJsonMessage(String to, String messageId,
Map<String, String> payload, String collapseKey, Long timeToLive,
Boolean delayWhileIdle) {
Map<String, Object> message = new HashMap<String, Object>();
message.put("to", to);
if (collapseKey != null) {
message.put("collapse_key", collapseKey);
}
if (timeToLive != null) {
message.put("time_to_live", timeToLive);
}
if (delayWhileIdle != null && delayWhileIdle) {
message.put("delay_while_idle", true);
}
message.put("message_id", messageId);
message.put("data", payload);
return JSONValue.toJSONString(message);
}
/**
* Creates a JSON encoded ACK message for an upstream message received
* from an application.
*
* #param to RegistrationId of the device who sent the upstream message.
* #param messageId messageId of the upstream message to be acknowledged to CCS.
* #return JSON encoded ack.
*/
protected static String createJsonAck(String to, String messageId) {
Map<String, Object> message = new HashMap<String, Object>();
message.put("message_type", "ack");
message.put("to", to);
message.put("message_id", messageId);
return JSONValue.toJSONString(message);
}
/**
* Connects to GCM Cloud Connection Server using the supplied credentials.
*
* #param senderId Your GCM project number
* #param apiKey API Key of your project
*/
public void connect(long senderId, String apiKey)
throws XMPPException, IOException, SmackException {
ConnectionConfiguration config =
new ConnectionConfiguration(GCM_SERVER, GCM_PORT);
config.setSecurityMode(SecurityMode.enabled);
config.setReconnectionAllowed(true);
config.setRosterLoadedAtLogin(false);
config.setSendPresence(false);
config.setSocketFactory(SSLSocketFactory.getDefault());
connection = new XMPPTCPConnection(config);
connection.connect();
connection.addConnectionListener( new LoggingConnectionListener() );
// Handle incoming packets
connection.addPacketListener(new PacketListener() {
#Override
public void processPacket(Packet packet) {
logArea.logMessage( "Received: " + packet.toXML() );
Message incomingMessage = (Message) packet;
GcmPacketExtension gcmPacket =
(GcmPacketExtension) incomingMessage.
getExtension(GCM_NAMESPACE);
String json = gcmPacket.getJson();
try {
#SuppressWarnings("unchecked")
Map<String, Object> jsonObject =
(Map<String, Object>) JSONValue.
parseWithException(json);
// present for "ack"/"nack", null otherwise
Object messageType = jsonObject.get("message_type");
if (messageType == null) {
// Normal upstream data message
handleUpstreamMessage(jsonObject);
// Send ACK to CCS
String messageId = (String) jsonObject.get("message_id");
String from = (String) jsonObject.get("from");
String ack = createJsonAck(from, messageId);
send(ack);
} else if ("ack".equals(messageType.toString())) {
// Process Ack
handleAckReceipt(jsonObject);
} else if ("nack".equals(messageType.toString())) {
// Process Nack
handleNackReceipt(jsonObject);
} else if ("control".equals(messageType.toString())) {
// Process control message
handleControlMessage(jsonObject);
} else {
logArea.logMessage( "Unrecognised message type: " +
messageType.toString() );
}
} catch (ParseException e) {
logArea.logMessage( "Error parsing JSON " + json );
} catch (Exception e) {
logArea.logMessage( "Failed to process packet" );
}
}
}, new PacketTypeFilter(Message.class));
// Log all outgoing packets
connection.addPacketInterceptor(new PacketInterceptor() {
#Override
public void interceptPacket(Packet packet) {
logArea.logMessage( "Sent: " + packet.toXML());
}
}, new PacketTypeFilter(Message.class));
connection.login(senderId + "#gcm.googleapis.com", apiKey);
}
//---------- support classes ----------
/**
* XMPP Packet Extension for GCM Cloud Connection Server.
*/
private static class GcmPacketExtension extends DefaultPacketExtension {
private final String json;
public GcmPacketExtension(String json) {
super( GCM_ELEMENT_NAME, GCM_NAMESPACE);
this.json = json;
}
public String getJson() {
return json;
}
#Override
public String toXML() {
return String.format("<%s xmlns=\"%s\">%s</%s>",
GCM_ELEMENT_NAME, GCM_NAMESPACE,
StringUtils.escapeForXML(json), GCM_ELEMENT_NAME);
}
public Packet toPacket() {
Message message = new Message();
message.addExtension(this);
return message;
}
}
class LoggingConnectionListener implements ConnectionListener {
#Override
public void connected(XMPPConnection xmppConnection) {
logArea.logMessage( "Connected." );
}
#Override
public void authenticated(XMPPConnection xmppConnection) {
logArea.logMessage( "Authenticated." );
}
#Override
public void reconnectionSuccessful() {
logArea.logMessage( "Reconnecting.." );
}
#Override
public void reconnectionFailed(Exception e) {
logArea.logMessage( "Reconnection failed.. " + e.getMessage() );
}
#Override
public void reconnectingIn(int seconds) {
logArea.logMessage( "Reconnecting in " + seconds + " secs" );
}
#Override
public void connectionClosedOnError(Exception e) {
logArea.logMessage( "Connection closed on error." );
}
#Override
public void connectionClosed() {
logArea.logMessage( "Connection closed." );
}
}
}
// a non-editable combo (drop-down) box for destination addresses
class DestComboBox extends JComboBox<String> {
// (deleted to save space)
}
// screen panel for sending a message
class SendMessagePanel extends JPanel implements ActionListener, ItemListener {
// Message Types
protected final int MSGTYPE_NOTIFICATION = 1;
protected final int MSGTYPE_NOTIFICATION_DATA = 2;
protected final int MSGTYPE_DATA_COLLAPSE = 3;
protected final int MSGTYPE_DATA_NONCOLLAPSE = 4;
// log window
LogTextArea msgs;
// server class
CcsServer ccsServer;
// constructor
SendMessagePanel( UserList u, LogTextArea m, CcsServer c ) {
// (deleted to save space)
}
// respond to the button
#Override
public void actionPerformed(ActionEvent e) {
String toAddr = "zzzzzz"; // destination address
// may be device, notification_key, or topic address
ttl = 2419200; // time-to-live in seconds
// what type of message?
int msgTypeIndex = (--deleted--);
// create the message
Map<String, Object> message = new HashMap<String, Object>();
message.put("to", toAddr);
if ( msgTypeIndex == MSGTYPE_NOTIFICATION ||
msgTypeIndex == MSGTYPE_NOTIFICATION_DATA ||
msgTypeIndex == MSGTYPE_DATA_COLLAPSE ) {
// create a collapse key
message.put("collapse_key", "ck"+msgTypeIndex );
}
message.put("time_to_live", ttl);
message.put("message_id", ccsServer.nextMessageId());
// notification included?
if ( msgTypeIndex == MSGTYPE_NOTIFICATION ||
msgTypeIndex == MSGTYPE_NOTIFICATION_DATA ) {
// create the notification payload
HashMap<String, String> notePayload = new HashMap<>();
notePayload.put( "title", "Gcm Push Message Example" );
notePayload.put( "body", (--deleted--) );
// identify which notifications should replace older versions
notePayload.put( "tag", "ntag" + msgTypeIndex );
notePayload.put( "icon", "#drawable/new_picture" ); // notification icon
// additional stuff if we also have data
if ( msgTypeIndex == MSGTYPE_NOTIFICATION_DATA ) {
// what to do when the user opens the notification
notePayload.put( "click_action", "OPEN_MAIN_ACTIVITY" );
}
message.put( "notification", notePayload );
}
// data included?
if ( msgTypeIndex == MSGTYPE_NOTIFICATION_DATA ||
msgTypeIndex == MSGTYPE_DATA_COLLAPSE ||
msgTypeIndex == MSGTYPE_DATA_NONCOLLAPSE ) {
HashMap<String, String> dataPayload = new HashMap<>();
dataPayload.put( "contents", (--deleted--) );
message.put("data", dataPayload);
}
// actually send the message
try {
ccsServer.sendDownstreamMessage( JSONValue.toJSONString(message) );
} catch (NotConnectedException enc ) {
msgs.logMessage( "Not connected anymore, echo message is not sent: " + enc.getMessage() );
}
}
}
class BorderPanel extends JPanel {
// (--deleted--)
}
public class GcmPushServer
{
// (--deleted--)
}
Google's example implementation of an XMPP server is in the friendly-ping sample. It has Java and Go versions.
A little bit late, but here's:
The direct link to the sample app server for ccs connection Friendly Ping java
Wolfram Rittmeyer also created a gcm server, in his An XMPP Server for Google Cloud Messaging post
I want to test MessageProcessor1.listAllKeyword method, which in turn
calls HbaseUtil1.getAllKeyword method. Initialy, I had to deal with a problem associated with the static initializer and the constructor. The problem was to initialize a HBASE DB connection. I used powerMock to suppress static and constructor calls and it worked fine.
Even though I mocked HbaseUtil1.getAllKeyword method, actual method is being called and executes all HBase code leading to an exception, in which HBASE server is not up.
EasyMock.expect(hbaseUtil.getAllKeyword("msg", "u1")).andReturn(expectedList);
Please give me any idea on how to avoid an actual method call. I tried many ways but none of them worked.
public class MessageProcessor1
{
private static Logger logger = Logger.getLogger("MQ-Processor");
private final static String CLASS_NAME = "MessageProcessor";
private static boolean keywordsTableExists = false;
public static PropertiesLoader props;
HbaseUtil1 hbaseUtil;
/**
* For checking if table exists in HBase. If doesn't exists, will create a
* new table. This runs only once when class is loaded.
*/
static {
props = new PropertiesLoader();
String[] userTablefamilys = {
props.getProperty(Constants.COLUMN_FAMILY_NAME_COMMON_KEYWORDS),
props.getProperty(Constants.COLUMN_FAMILY_NAME_USER_KEYWORDS) };
keywordsTableExists = new HbaseUtil()
.creatTable(props.getProperty(Constants.HBASE_TABLE_NAME),
userTablefamilys);
}
/**
* This will load new configuration every time this class instantiated.
*/
{
props = new PropertiesLoader();
}
public String listAllKeyword(String userId) throws IOException {
HbaseUtil1 util = new HbaseUtil1();
Map<String, List<String>> projKeyMap = new HashMap<String, List<String>>();
//logger.info(CLASS_NAME+": inside listAllKeyword method");
//logger.debug("passed id : "+userId);
List<String> qualifiers = util.getAllKeyword("msg", userId);
List<String> keywords = null;
for (String qualifier : qualifiers) {
String[] token = qualifier.split(":");
if (projKeyMap.containsKey(token[0])) {
projKeyMap.get(token[0]).add(token[1]);
} else {
keywords = new ArrayList<String>();
keywords.add(token[1]);
projKeyMap.put(token[0], keywords);
}
}
List<Project> projects = buildProject(projKeyMap);
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
.create();
System.out.println("Json projects:::" + gson.toJson(projects));
//logger.debug("list all keyword based on project::::"+ gson.toJson(projects));
//return gson.toJson(projects);
return "raj";
}
private List<Project> buildProject(Map<String, List<String>> projKeyMap) {
List<Project> projects = new ArrayList<Project>();
Project proj = null;
Set<String> keySet = projKeyMap.keySet();
for (String hKey : keySet) {
proj = new Project(hKey, projKeyMap.get(hKey));
projects.add(proj);
}
return projects;
}
//#Autowired
//#Qualifier("hbaseUtil1")
public void setHbaseUtil(HbaseUtil1 hbaseUtil) {
this.hbaseUtil = hbaseUtil;
}
}
public class HbaseUtil1 {
private static Logger logger = Logger.getLogger("MQ-Processor");
private final static String CLASS_NAME = "HbaseUtil";
private static Configuration conf = null;
public HbaseUtil1() {
PropertiesLoader props = new PropertiesLoader();
conf = HBaseConfiguration.create();
conf.set(HConstants.ZOOKEEPER_QUORUM, props
.getProperty(Constants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM));
conf.set(
HConstants.ZOOKEEPER_CLIENT_PORT,
props.getProperty(Constants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENT_PORT));
conf.set("hbase.zookeeper.quorum", props
.getProperty(Constants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM));
conf.set(
"hbase.zookeeper.property.clientPort",
props.getProperty(Constants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENT_PORT));
}
public List<String> getAllKeyword(String tableName, String rowKey)
throws IOException {
List<String> qualifiers = new ArrayList<String>();
HTable table = new HTable(conf, tableName);
Get get = new Get(rowKey.getBytes());
Result rs = table.get(get);
for (KeyValue kv : rs.raw()) {
System.out.println("KV: " + kv + ", keyword: "
+ Bytes.toString(kv.getRow()) + ", quaifier: "
+ Bytes.toString(kv.getQualifier()) + ", family: "
+ Bytes.toString(kv.getFamily()) + ", value: "
+ Bytes.toString(kv.getValue()));
qualifiers.add(new String(kv.getQualifier()));
}
table.close();
return qualifiers;
}
/**
* Create a table
*
* #param tableName
* name of table to be created.
* #param familys
* Array of the name of column families to be created with table
* #throws IOException
*/
public boolean creatTable(String tableName, String[] familys) {
HBaseAdmin admin = null;
boolean tableCreated = false;
try {
admin = new HBaseAdmin(conf);
if (!admin.tableExists(tableName)) {
HTableDescriptor tableDesc = new HTableDescriptor(tableName);
for (int i = 0; i < familys.length; i++) {
tableDesc.addFamily(new HColumnDescriptor(familys[i]));
}
admin.createTable(tableDesc);
System.out.println("create table " + tableName + " ok.");
}
tableCreated = true;
admin.close();
} catch (MasterNotRunningException e1) {
e1.printStackTrace();
} catch (ZooKeeperConnectionException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return tableCreated;
}
}
Below is my Test class.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MessageProcessor1.class)
#SuppressStaticInitializationFor("com.serendio.msg.mqProcessor.MessageProcessor1")
public class MessageProcessorTest1 {
private MessageProcessor1 messageProcessor;
private HbaseUtil1 hbaseUtil;
#Before
public void setUp() {
messageProcessor = new MessageProcessor1();
hbaseUtil = EasyMock.createMock(HbaseUtil1.class);
}
#Test
public void testListAllKeyword(){
List<String> expectedList = new ArrayList<String>();
expectedList.add("raj:abc");
suppress(constructor(HbaseUtil1.class));
//suppress(method(HbaseUtil1.class, "getAllKeyword"));
try {
EasyMock.expect(hbaseUtil.getAllKeyword("msg", "u1")).andReturn(expectedList);
EasyMock.replay();
assertEquals("raj", messageProcessor.listAllKeyword("u1"));
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
}
}
The HbaseUtil1 is instantiated within the listAllKeyword method
public String listAllKeyword(String userId) throws IOException {
HbaseUtil1 util = new HbaseUtil1();
...
So the mock one you create in your test isn't being used at all.
If possible, make the HbaseUtil1 object passable, or settable on the MessageProcessor1 class and then set it in the test class.
Also, and note I'm not 100% familiar with PowerMock, you could include HbaseUtil1 in the prepare for test annotation. I think that will make PowerMock instantiate mocks instead of real objects and then use the expectations you provide in you test.
The incoming data has to be fed back into the polling method and also should be processed further for another class.
public List<KAAMessage> fullPoll() throws Exception {
Statement st = dbConnection.createStatement();
ResultSet rs = st.executeQuery("select * from msg_new_to_bde where ACTION = 804 order by SEQ DESC");
List<KpiMessage> pojoCol = new ArrayList<KpiMessage>();
while (rs.next()) {
KpiMessage filedClass = convertRecordsetToPojo(rs);
pojoCol.add(filedClass);
}
return pojoCol;
}
/**
* Converts a provided record-set to a {#link KpiMessage}.
*
* The following attributes are copied from record-set to pojo:
*
* <ul>
* <li>SEQ</li>
* <li>TABLENAME</li>
* <li>ENTRYTIME</li>
* <li>STATUS</li>
* </ul>
*
* #param rs
* the record-set to convert
* #return the converted pojo class object
* #throws SQLException
* if an sql error occurs during processing of recordset
*/
private KpiMessage convertRecordsetToPojo(ResultSet rs) throws SQLException {
KpiMessage msg = new KpiMessage();
int sequence = rs.getInt("SEQ");
msg.setSequence(sequence);
int action = rs.getInt("ACTION");
msg.setAction(action);
String tablename = rs.getString("TABLENAME");
msg.setTableName(tablename);
Timestamp entrytime = rs.getTimestamp("ENTRYTIME");
Date entryTime = new Date(entrytime.getTime());
msg.setEntryTime(entryTime);
Timestamp processingtime = rs.getTimestamp("PROCESSINGTIME");
if (processingtime != null) {
Date processingTime = new Date(processingtime.getTime());
msg.setProcessingTime(processingTime);
}
String keyInfo1 = rs.getString("KEYINFO1");
msg.setKeyInfo1(keyInfo1);
String keyInfo2 = rs.getString("KEYINFO2");
msg.setKeyInfo2(keyInfo2);
return msg;
}
This class has the Poll() method which reads message from the database. In the database I have SequeceID as unique number and it keeps on increasing for new data, but how can I get this new messages and feed it back to polling?
P.S: Please comment if you are down voting or closing my post because I am new here and I'd like to know the details.
this the Controller Class which runs the thread for the Poll() method.
public class RunnableController {
/** Here This Queue initializes the DB and have the collection of incoming message
*
*/
private static Collection<KaMessage> incomingQueue = new ArrayList<KAMessage>();
private Connection dbConncetion;
private ExecutorService threadExecutor;
private void initializeDb()
{
//catching exception must be adapted - generic type Exception prohibited
DBhandler con = new DBhandler();
try {
dbConncetion = con.initializeDB();
} catch (Exception e) {
e.printStackTrace();
}
}
private void initialiseThreads()
{
try {
threadExecutor = Executors.newFixedThreadPool(10);
PollingSynchronizer read = new PollingSynchronizer(incomingQueue,
dbConncetion);
threadExecutor.submit(read);
}catch (Exception e){
e.printStackTrace();
}
}
private void shutDownThreads()
{
try {
threadExecutor.shutdown();
dbConncetion.close();
}catch (Exception e){
e.printStackTrace();
}
}
/** Here This Queue passes the messages and have the collection of outgoing message
*
*/
// private Collection<KpiMessage> outgingQueue = new ArrayList<KpiMessage>();
/**
* Main
*
* #param args
* #throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
RunnableController controller = new RunnableController();
System.out.println(incomingQueue.size());
controller.initializeDb();
controller.initialiseThreads();
System.out.println("Repetetive polling for each 6 seconds");
KpiProcessor kp = new KpiProcessor();
try {
} catch (Exception e) {
e.printStackTrace();
}
}
}
I have a Berkeley-db database where both 'key' and 'value' are of type integer. Is there any way to traverse the database in descending order of 'value'?
I'm using Berkeley-db je-5.0.58 API. The sample code that i'm using from its documentation is shown below.
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2004-2010 Oracle. All rights reserved.
*
*/
package je;
import java.io.File;
import com.sleepycat.bind.tuple.IntegerBinding;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.Transaction;
/**
* SimpleExample creates a database environment, a database, and a database
* cursor, inserts and retrieves data.
*/
class SimpleExample {
private static final int EXIT_SUCCESS = 0;
private static final int EXIT_FAILURE = 1;
private int numRecords; // num records to insert or retrieve
private int offset; // where we want to start inserting
private boolean doInsert; // if true, insert, else retrieve
private File envDir;
public SimpleExample(int numRecords,
boolean doInsert,
File envDir,
int offset) {
this.numRecords = numRecords;
this.doInsert = doInsert;
this.envDir = envDir;
this.offset = offset;
}
/**
* Usage string
*/
public static void usage() {
System.out.println("usage: java " +
"je.SimpleExample " +
"<dbEnvHomeDirectory> " +
"<insert|retrieve> <numRecords> [offset]");
System.exit(EXIT_FAILURE);
}
/**
* Main
*/
public static void main(String argv[]) {
if (argv.length < 2) {
usage();
return;
}
File envHomeDirectory = new File(argv[0]);
boolean doInsertArg = false;
if (argv[1].equalsIgnoreCase("insert")) {
doInsertArg = true;
} else if (argv[1].equalsIgnoreCase("retrieve")) {
doInsertArg = false;
} else {
usage();
}
int startOffset = 0;
int numRecordsVal = 0;
if (doInsertArg) {
if (argv.length > 2) {
numRecordsVal = Integer.parseInt(argv[2]);
} else {
usage();
return;
}
if (argv.length > 3) {
startOffset = Integer.parseInt(argv[3]);
}
}
try {
SimpleExample app = new SimpleExample(numRecordsVal,
doInsertArg,
envHomeDirectory,
startOffset);
app.run();
} catch (DatabaseException e) {
e.printStackTrace();
System.exit(EXIT_FAILURE);
}
System.exit(EXIT_SUCCESS);
}
/**
* Insert or retrieve data
*/
public void run() throws DatabaseException {
/* Create a new, transactional database environment */
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setTransactional(true);
envConfig.setAllowCreate(true);
Environment exampleEnv = new Environment(envDir, envConfig);
/*
* Make a database within that environment
*
* Notice that we use an explicit transaction to
* perform this database open, and that we
* immediately commit the transaction once the
* database is opened. This is required if we
* want transactional support for the database.
* However, we could have used autocommit to
* perform the same thing by simply passing a
* null txn handle to openDatabase().
*/
Transaction txn = exampleEnv.beginTransaction(null, null);
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setTransactional(true);
dbConfig.setAllowCreate(true);
dbConfig.setSortedDuplicates(true);
Database exampleDb = exampleEnv.openDatabase(txn,
"simpleDb",
dbConfig);
txn.commit();
/*
* Insert or retrieve data. In our example, database records are
* integer pairs.
*/
/* DatabaseEntry represents the key and data of each record */
DatabaseEntry keyEntry = new DatabaseEntry();
DatabaseEntry dataEntry = new DatabaseEntry();
if (doInsert) {
/* put some data in */
for (int i = offset; i < numRecords + offset; i++) {
/*
* Note that autocommit mode, described in the Getting
* Started Guide, is an alternative to explicitly
* creating the transaction object.
*/
txn = exampleEnv.beginTransaction(null, null);
/* Use a binding to convert the int into a DatabaseEntry. */
IntegerBinding.intToEntry(i, keyEntry);
IntegerBinding.intToEntry(i+1, dataEntry);
OperationStatus status =
exampleDb.put(txn, keyEntry, dataEntry);
/*
* Note that put will throw a DatabaseException when
* error conditions are found such as deadlock.
* However, the status return conveys a variety of
* information. For example, the put might succeed,
* or it might not succeed if the record alread exists
* and the database was not configured for duplicate
* records.
*/
if (status != OperationStatus.SUCCESS) {
throw new RuntimeException("Data insertion got status " +
status);
}
txn.commit();
}
} else {
/* retrieve the data */
Cursor cursor = exampleDb.openCursor(null, null);
while (cursor.getNext(keyEntry, dataEntry, LockMode.DEFAULT) ==
OperationStatus.SUCCESS) {
System.out.println("key=" +
IntegerBinding.entryToInt(keyEntry) +
" data=" +
IntegerBinding.entryToInt(dataEntry));
}
cursor.close();
}
exampleDb.close();
exampleEnv.close();
}
}
you can use a custom comparator and use a cursor to traverse the data in descending order.
In java you have to implement a custom Comparator:
EDIT:
import java.util.Comparator;
import com.sleepycat.bind.tuple.IntegerBinding;
import com.sleepycat.je.DatabaseEntry;
public class IntegerSorter implements Comparator<byte[]>
{
#Override
public int compare(byte[] o1, byte[] o2)
{
return
IntegerBinding.entryToInt(new DatabaseEntry(o1)) -
IntegerBinding.entryToInt(new DatabaseEntry(o2));
}
}
(...)
dbConfig.setBtreeComparator(IntegerSorter.class);
(...)