I'm using the PubNub API with Java for pulling data from MtGox.
When retrieving data, the API delivers it in form of a JSONObject, which represents a tree structure of JSON data. Trying to extract bits of information directly from a JSONObject produces ugly code with lots of calls to getJSONObject(String), for which again exceptions might need to be handled.
Therefor, I'm looking for a convenient way to extract information from the JSONObject responses. So far, I've come across the possibility to convert the JSONObject into a POJO and then access the POJO. For conversion, I found the ObjectMapper from the Jackson library, which does a nice job here:
public void successCallback(String channel, Object message) {
JSONObject messageJson = (JSONObject) message;
ObjectMapper mapper = new ObjectMapper();
Message myMessage = mapper.readValue(messageJson.toString(), Message.class);
// do stuff with myMessage here
}
This approach has the disadvantage that I have to write my own POJO classes, e.g. the Message class in the above example, because I could not find these classes ready to use anywhere.
How to conveniently access the information stored in the JSONObject?
PubNub Java Class for MtGox JSON API
It's easy to create a ready made Java Class for ingesting the live feed provided by Mt.Gox This is a work-in-progress post to show you how to access the PubNub Data Feed from Mt.Gox as shown in the Dev Console live feed!
Official Bitcoin Wiki JSON Streaming API
We will be working from the Bitcoin wiki feed instructions provided by Bitcoin official Wiki: https://en.bitcoin.it/wiki/MtGox/API/Pubnub - continue reading below the screenshot to continue.
To see the live real-time data feed we will be using, please checkout the following two links:
Live Feed Trade Events (Buy/Sell Feed): https://www.pubnub.com/console?sub=sub-c-50d56e1e-2fd9-11e3-a041-02ee2ddab7fe&pub=demo&channel=dbf1dee9-4f2e-4a08-8cb7-748919a71b21&origin=pubsub.pubnub.com&ssl=true
Live Feed Ticker Updates (Price Changes): https://www.pubnub.com/console?sub=sub-c-50d56e1e-2fd9-11e3-a041-02ee2ddab7fe&pub=demo&channel=d5f06780-30a8-4a48-a2f8-7ed181b4a13f&origin=pubsub.pubnub.com&ssl=true
Trade Lag Example: https://www.mtgox.com/lag.html
PubNub Java SDK Docs
We will be using the PubNub Java SDK Docs
http://www.pubnub.com/docs/java/javase/overview/data-push.html
Specifically we'll be using the mtgox.subcribe(...) instance method to focus our efforts which looks like the following:
Download JAR or Source: https://github.com/pubnub/mtgox
import org.json.JSONObject;
import com.pubnub.mtgox.MtGox;
import com.pubnub.mtgox.MtGoxCallback;
public class PubnubMtGoxSample {
public static void main(String[] args) {
MtGox mtgx = new MtGox();
mtgx.subscribe("ticker.BTCUSD", new MtGoxCallback(){
#Override
public void callback(JSONObject data) {
try {
String channel_name = data.getString("channel_name");
String avg_value = data.getJSONObject("ticker").getJSONObject("avg").getString("value");
System.out.println(channel_name + " : " + avg_value);
} catch (Exception e) {}
}});
}
}
See Full MtGox Example with Java Source Code - https://github.com/pubnub/mtgox/blob/master/java/examples/PubnubMtGoxSample.java
To compile the example got to https://github.com/pubnub/mtgox/tree/master/java and run
javac -cp Pubnub-MtGox.jar:libs/json-20090211.jar examples/PubnubMtGoxSample.java
And then to RUN:
java -cp .:examples/:Pubnub-MtGox.jar:Pubnub-StandardEdition-3.5.6.jar:libs/json-20090211.jar:libs/bcprov-jdk15on-1.47.jar:libs/slf4j-api-1.7.5.jar:libs/slf4j-nop-1.7.5.jar PubnubMtGoxSample
The Concept
For me, the best solution was to convert the JSONObjects from the PubNub API to bean classes which I found in the MtGox module of the XChange library.
Admitted, this approach adds quite a bit of glue code as you can see at the end of this answer, but I think it's worth the trouble, because after the conversion, the code gets much simpler. E.g. for getting the rate and currency from the ticker at which BTC was last traded, you can simply write
ticker.getLast().getValue()
and
ticker.getLast().getCurrency()
How To Do It
The mtgox module of the XChange library is available as a maven artifact, which is very convenient. You only need to add this module as a dependency to your project and the project setup is done.
In the xchange-mtgox module, you will find the package com.xeiam.xchange.mtgox.v2.dto.marketdata with the two calsses MtGoxTrade and MtGoxTicker.
Converting from JSONObject to one of these classes is easy with the Jackson ObjectMapper. As an advantage, the Jackson library is automatically imported as a transitive dependency of the xchange-mtgox maven artifact. That means that if you're using maven, you don't even have to write a single line of code to add it to your project.
Below is a complete runnable Example. Most is standard code for using PubNub. The important bits are between the marks // BEGIN OF IMPORTANT PART and // END OF IMPORTANT PART.
public class PubNubMtGoxBeanExample {
private static final String MTGOXPUBNUB_SUBSCRIBE_KEY = "sub-c-50d56e1e-2fd9-11e3-a041-02ee2ddab7fe";
private static final String MTGOXPUBNUB_BTCEUR_CHANNEL = "0bb6da8b-f6c6-4ecf-8f0d-a544ad948c15";
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
static {
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public static void main(String[] args) throws PubnubException {
Pubnub pubnub = new Pubnub("demo", MTGOXPUBNUB_SUBSCRIBE_KEY);
pubnub.subscribe(MTGOXPUBNUB_BTCEUR_CHANNEL, new Callback() {
#Override
public void successCallback(String channel, Object message) {
// BEGIN OF IMPORTANT PART
JSONObject messageJson = (JSONObject) message;
JSONObject tickerJson;
try {
tickerJson = messageJson.getJSONObject("ticker");
} catch (JSONException e) {
throw new RuntimeException(e);
}
MtGoxTicker ticker;
try {
// the following line is the most important, because it maps from the JSONObject to the MtGoxTicker class
ticker = OBJECT_MAPPER.readValue(tickerJson.toString(), MtGoxTicker.class);
} catch (JsonParseException e) {
throw new RuntimeException(e);
} catch (JsonMappingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
String currency = ticker.getLast().getCurrency();
BigDecimal value = ticker.getLast().getValue();
System.out.println(currency + " " + value);
// END OF IMPORTANT PART
}
#Override
public void connectCallback(String channel, Object message) {
System.out.println("connectCallback on channel:" + channel + " : " + message.getClass() + " : " + message.toString());
}
#Override
public void disconnectCallback(String channel, Object message) {
System.out.println("disconnectCallback on channel:" + channel + " : " + message.getClass() + " : " + message.toString());
}
#Override
public void reconnectCallback(String channel, Object message) {
System.out.println("reconnectCallback on channel:" + channel + " : " + message.getClass() + " : " + message.toString());
}
#Override
public void errorCallback(String channel, PubnubError error) {
System.out.println("errorCallback on channel " + channel + " : " + error.toString());
}
});
}
}
For clarity, I've removed the imports, which you can add back in with the appropriate hotkeys in most IDEs (it's Ctrl+Shift+O in Eclipse).
Morevoer, note that there is a performance penalty in this code, which can be avoided by following the answer to the question
How to efficiently map a org.json.JSONObject to a POJO?
Related
I had the following problem: I have a service where I want to dynamically render templates using qute. Whose names I don't currently know (because they are passed via the endpoint).
Unfortunately Quarkus itself doesn't give the possibility to say "Template t = new Template()".... You always have to define them via inject at the beginning of a class. After a long time of searching and thinking about it, I have the following solution:
The solution is to inject the Quarkus Template Engine instead of a Template. The Engine could render a template directly.... Then we only have to read our template file as a String (Java 11 can read Files.readString(path, encoding)) and render it with our data map.
#Path("/api")
public class YourResource {
public static final String TEMPLATE_DIR = "/templates/";
#Inject
Engine engine;
#POST
public String loadTemplateDynamically(String locale, String templateName, Map<String, String> data) {
File currTemplate = new File(YourResource.class.getResource("/").getPath() + TEMPLATE_DIR + locale + "/" + templateName + ".html"); // this generates a String like <yourResources Folder> + /templates/<locale>/<templateName>.html
try {
Template t = engine.parse(Files.readString(currTemplate.getAbsoluteFile().toPath(), StandardCharsets.UTF_8));
//this render your data to the template... you also could specify it
return t.data(data.render());
} catch (IOException e) {
e.printStackTrace();
}
return "template not exists";
}
}
I'm trying to get a json file from remote host and parsing it via GSON.
Therefore I'm calling my function
private void initData() {
placeArrayList = PlaceRepository.getPlaceList();
}
In my PlaceRepository-class
public static ArrayList<Place> getPlaceList() {
return new Gson().fromJson(json, new TypeToken<ArrayList<Place>>(){}.getType());
}
and the referenced json is a static string:
static String json = "[\n" +
" {\n" +
" \"id\":\"GardensByTheBay\",\n" + ...
Thats absoluty working.
But now I would like to use remote json data from my server.
I'm sure that I have to use something like asynctask, right? Because I tried to load the json file and it failed with an NetworkOnMainThreadException.
Thank you!
As the title says, I need a way(no matter if its complicated or not) to create a getData() method that would send request packet to the server > receive the message I already have the system setup but I have a problem with it that I only get the result in PluginMessageReceiveEvent Here's my code with explanations:
public String requestData(String path) {
SocketUtils.sendData("REQUEST|" + p.getPlayer().getUniqueId() + "|" + path, "playerconfig", "BUNGEE");
return /*Need to get data from the plugin message to here*/;
}
#EventHandler
public void onPluginMessageReceive(PluginMessageReceiveEvent e) {
if (e.getChannel().equalsIgnoreCase("playerconfig")) {
String[] args = e.getMessage().split("\\|");
String uuid = args[0];
String path = args[1];//Maybe a HashMap<Path, Data> but that would make the requestData() result return null because you don't get the data instantly.
String data = args[2].replace("_", " ");
if (uuid.equals(p.getPlayer().getUniqueId() + "")) {
return data; //I need to get this result on request data method.
}
}
}
A simple solution is to wait on a lock in the requestData and notify that lock in onPluginMessageReceive. Something like this:
synchronized(this) {
wait();
}
And in your receive method:
synchronized(this) {
notifyAll();
}
Make the data a member field of the class.
Look out for exception handling and syntax errors.
I can load a grammar file in to my java project (in netbeans) and generate/build my lexer and parser classes, load them via reflection and then parse what I need to parse.
What I would like is a simple example of redirecting the results from the generate/build of the lexer and parser to a string so that I can put the errors to a popup like JOptionPane.
Just like ANTLRworks does when you do CTRL-R (in windows at least) showing Error(123) grammar.g:100:12: ...Warning...etc...
Now I am already using a DiagnosticCollector but this does not always enough details as the CTRL-r in ANTLRworks does. The idea being the user corrects the grammar in order to correct the mistake.
Here's a snippet of my code
Tool tool = new Tool(new String[]{userDir + grammarPath + grammarName + ".g"});
//tool.setOutputDirectory(userDir + grammarPath );
tool.process();
if(tool.getNumErrors()>0) {
errors=true;
unableToLoadGrammar_AddLine("1. Detected "+tool.getNumErrors()+" Error(s)"+tool.toString()+"\n");
}
Thanks
Call org.antlr.tool.ErrorManager's setErrorListener method:
public class ToolTest {
public static void main(String[] args) {
org.antlr.Tool tool = new org.antlr.Tool(new String[] { "GrammarWithErrors.g" });
final ArrayList<String> messages = new ArrayList<String>();
ErrorManager.setErrorListener(new ANTLRErrorListener() {
#Override
public void warning(Message msg) {
messages.add("Warning: " + msg.toString());
}
#Override
public void info(String msg) {
messages.add("Info: " + msg.toString());
}
#Override
public void error(ToolMessage msg) {
messages.add("Tool Error: " + msg.toString());
}
#Override
public void error(Message msg) {
messages.add("General Error: " + msg.toString());
}
});
tool.process();
System.out.println("Done processing...");
for (String msg : messages) {
System.out.println(msg);
}
}
}
Passing a bad grammar to the code above produces the following output:
Done processing...
General Error: error(100): GrammarWithErrors.g:1:14: syntax error: antlr: MismatchedTokenException(74!=52)
Tool Error: error(150): grammar file GrammarWithErrors.g has no rules
General Error: error(100): GrammarWithErrors.g:82:7: syntax error: assign.types: NoViableAltException(0#[])
Note that Tool still operates directly on System.err and System.out. If you want to handle everything coming out of Tool, you'll have to call System.setErr and System.setOut as well.
can anyone please tell me how to use google places api in android. I am developing this application in eclipse where i need to find the nearest petrol stations and garages near my area. I went through numerous websites. i didnt find a proper answer. I need a sample code since i am new to json concepts.
public class place {
private static final String PLACES_SEARCH_URL = "https://maps.googleapis.com/maps/api/place/search/json?";
private static final boolean PRINT_AS_STRING = false;
public void performSearch() throws Exception {
try {
System.out.println("Perform Search ....");
System.out.println("-------------------");
HttpRequestFactory httpRequestFactory = createRequestFactory(transport);
HttpRequest request = httpRequestFactory.buildGetRequest(new GenericUrl(PLACES_SEARCH_URL));
request.url.put("key", "api key");
request.url.put("location", lat + "," + lng);
request.url.put("radius", 500);
request.url.put("sensor", "false");
if (PRINT_AS_STRING) {
System.out.println(request.execute().parseAsString());
} else {
PlacesList places = request.execute().parseAs(PlacesList.class);
System.out.println("STATUS = " + places.status);
for (Place place : places.results) {
System.out.println(place);
}
}
} catch (HttpResponseException e) {
System.err.println(e.response.parseAsString());
throw e;
}
}//StoresNearMe
You can use Google API Java Client for Google Places API in Android . See my answer for a short snippet https://stackoverflow.com/a/12824796/1147466