I am trying to use Eventful API to get a list of events nearby but wasn't able to get any result with the request.
Does anyone know what is the problem here?
This is my JSON request: String url_request = "http://eventful.com/json/events?q=music&l=Singapore&api_key=" + API_KEY;
This is my current output :
{"sponsored_search_data":null,"location":{"geo_ip_fail":"0","location_type":null,"location_id":null,"geo_ip_guess":null,"meta_name":"Worldwide","pretty_name":"Worldwide"},"localized_base_url":"http://eventful.com","is_default_eventful_site":"1","facebook_app_namespace":"eventful","home_url":"/"}
package EventTest.EventTest;
import java.io.IOException;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
public class App
{
private static final String API_KEY = "my_api_key";
OkHttpClient client = new OkHttpClient();
public static void main( String[] args ) throws IOException
{
App request = new App();
String url_request = "http://eventful.com/json/events?q=music&l=Singapore&api_key=" + API_KEY;
String response = request.run(url_request);
System.out.println(response);
}
public String run(String url) throws IOException {
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
return response.body().string();
}
}
Manage to obtain desired result by changing the JSON request :
String url_request =
"http://api.eventful.com/json/events/search?keywords=music&location=Singapore&app_key=my_app_key";
Related
I have a server that handles requests, and with regular intervals (every 1-2 minutes) needs to call another server and update a list of objects that is used to create the response to the request. Inspired by for example the accepted answer for this question, I tried to use the Schedule annotation, but can't get it to work.
How to run a background task in a servlet based web application?
A simplified view of the server is:
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet(name = "MyServer", urlPatterns = {"/data/*", "/scheduled/*"}, loadOnStartup = 1)
public class MyServlet extends HttpServlet {
private static final String UTF_8 = "UTF-8";
private static final String APPLICATION_JSON = "application/json";
private static final long serialVersionUID = 1L;
private static connector connector;
public MyServlet() {
super();
}
public void destroy() {}
#Override
public void init() throws ServletException {
connector = new connector();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = request.getServletPath();
String pathInfo = request.getPathInfo().substring(1);
response.setContentType(APPLICATION_JSON);
response.setCharacterEncoding(UTF_8);
if (path.endsWith("/data")) {
List<DataItem> dataItems = connector.currentData;
response.getWriter().write(JsonUtility.convertToJsonString(dataItems));
} else if (path.endsWith("/scheduled")) {
connector.fetchData();
response.getWriter().write("Done");
} else {
response.getWriter()
.write(pathInfo + " Is not Found but not returning 404");
return;
}
}
}
The connector class that is supposed to update the stored data from the other server at regular intervals is:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
#Startup
#Singleton
public class Connector {
public List<DataItem> currentData = new LinkedList<>();
#Lock(LockType.READ)
#Schedule(second = "*", minute = "*/2", hour = "*", persistent = false)
public void fetchNews() {
logger.debug("Fetching data");
String response = sendGet(url, bearerToken);
JsonObject json = new Gson().fromJson(response, JsonObject.class);
//Transform the response to a list of DataItems.
List<DataItem> retrievedData = toDataList(json)
System.out.println(retrievedData);
synchronized(currentData) {
currentData = retrievedData;
}
}
private String sendGet(String path, String authorizationProperty) {
URL url;
try {
url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", authorizationProperty);
conn.setRequestProperty("Content-Type","application/json");
conn.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String output;
StringBuffer response = new StringBuffer();
while ((output = in.readLine()) != null) {
response.append(output);
}
in.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
However, the method fetchData is not firing every second minute as I was expecting. I don't know what I am missing. I have played around a bit with adding/removing the #Startup annotation, creating an instance of the class in the init() method on the server, but still have no result.
We have JAX RS implementation which needs to send back JSON output. But the response size is huge. And the client expects the same synchronously.
Hence I tried to use StreamingOutput... but the client is not really getting the data in chunks.
Below is sample snippet:
Server Side
streamingOutput = new StreamingOutput() {
#Override
public void write(OutputStream out) throws IOException, WebApplicationException {
JsonGenerator jsonGenerator = mapper.getFactory().createGenerator(out);
jsonGenerator.writeStartArray();
for(int i=0; i < 10; i++) {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("Response_State", "Response State - " + i);
jsonGenerator.writeStringField("Response_Report", "Response Report - " + i);
jsonGenerator.writeStringField("Error_details", "Error Details - " + i);
jsonGenerator.writeEndObject();;
jsonGenerator.flush();
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
jsonGenerator.writeEndArray();
jsonGenerator.close();
}
};
return Response.status(200).entity(streamingOutput).build();
Client
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost("http://localhost:8080/AccessData/FetchReport");
post.setHeader("Content-type", "application/json");
ResponseHandler<HttpResponse> responseHandler = new BasicResponseHandler();
StringEntity entity = new StringEntity(jsonRequest); //jsonRequest is request string
post.setEntity(entity);
HttpResponse response = client.execute(post);
BufferedReader buffReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
JsonParser jsonParser = new JsonFactory().createParser(buffReader);
while(jsonParser.nextToken() != JsonToken.END_OBJECT) {
System.out.println(jsonParser.getCurrentName() + ":" + jsonParser.getCurrentValue());
}
String output;
while((output = buffReader.readLine()) != null) {
System.out.println(output);
}
In the server side code, I am putting sleep call just to simulate a gap between chunks of data. What I need is that the client should receive chunks of data as and when it is thrown back by the server.
But here the client gets the response in entirety always.
Any possible solution?
Thanks in advance.
It looks like the client side is not implemented correctly: reading the array of the objects using the parser.
Also, I would like to recommend reading and writing a data transfer object instead of low level field-by-field reading and writing.
For the sake of completeness, here is a complete draft example that uses: Jersey 2.25.1, Jetty 9.2.14.v20151106.
Common
ResponseData class
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class ResponseData {
private final String responseState;
private final String responseReport;
private final String errorDetails;
#JsonCreator
public ResponseData(
#JsonProperty("Response_State") final String responseState,
#JsonProperty("Response_Report") final String responseReport,
#JsonProperty("Error_details") final String errorDetails) {
this.responseState = responseState;
this.responseReport = responseReport;
this.errorDetails = errorDetails;
}
public String getResponseState() {
return this.responseState;
}
public String getResponseReport() {
return this.responseReport;
}
public String getErrorDetails() {
return this.errorDetails;
}
#Override
public String toString() {
return String.format(
"ResponseData: responseState: %s; responseReport: %s; errorDetails: %s",
this.responseState,
this.responseReport,
this.errorDetails
);
}
}
Service
ServerProgram class
import java.net.URI;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
import org.glassfish.jersey.server.ResourceConfig;
public class ServerProgram {
public static void main(final String[] args) {
final URI uri = URI.create("http://localhost:8080/");
final ResourceConfig resourceConfig = new ResourceConfig(TestResource.class);
resourceConfig.register(JacksonFeature.class);
JettyHttpContainerFactory.createServer(uri, resourceConfig);
}
}
TestResource class
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.OutputStream;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
#Path("/")
public class TestResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getData() {
final StreamingOutput streamingOutput = new JsonStreamingOutput();
return Response.status(200).entity(streamingOutput).build();
}
private static class JsonStreamingOutput implements StreamingOutput {
#Override
public void write(final OutputStream outputStream) throws IOException, WebApplicationException {
final ObjectMapper objectMapper = new ObjectMapper();
final JsonFactory jsonFactory = objectMapper.getFactory();
try (final JsonGenerator jsonGenerator = jsonFactory.createGenerator(outputStream)) {
jsonGenerator.writeStartArray();
for (int i = 0; i < 10; i++) {
final ResponseData responseData = new ResponseData(
"Response State - " + i,
"Response Report - " + i,
"Error Details - " + i
);
jsonGenerator.writeObject(responseData);
jsonGenerator.flush();
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
jsonGenerator.writeEndArray();
}
}
}
}
Client
ClientProgram class
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.MediaType;
import org.glassfish.jersey.client.ClientProperties;
public class ClientProgram {
public static void main(final String[] args) throws IOException {
Client client = null;
try {
client = ClientBuilder.newClient();
client.property(ClientProperties.READ_TIMEOUT, 10000);
try (final InputStream inputStream = client
.target("http://localhost:8080/")
.request(MediaType.APPLICATION_JSON)
.get(InputStream.class);
final BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {
processStream(bufferedInputStream);
}
} finally {
if (client != null) {
client.close();
}
}
}
private static void processStream(final InputStream inputStream) throws IOException {
final ObjectMapper objectMapper = new ObjectMapper();
final JsonFactory jsonFactory = objectMapper.getFactory();
try (final JsonParser jsonParser = jsonFactory.createParser(inputStream)) {
final JsonToken arrayToken = jsonParser.nextToken();
if (arrayToken == null) {
// TODO: Return or throw exception.
return;
}
if (!JsonToken.START_ARRAY.equals(arrayToken)) {
// TODO: Return or throw exception.
return;
}
// Iterate through the objects of the array.
while (JsonToken.START_OBJECT.equals(jsonParser.nextToken())) {
final ResponseData responseData = jsonParser.readValueAs(ResponseData.class);
System.out.println(responseData);
}
}
}
}
Hope this helps.
Java class
package voteHandler.Org.RSPSVote;
/*
* Author: Sieu Phan
* Website: RSPS Vote
* Data: 5/7/2014
* Version: 1.1
*/
import java.io.IOException;
import java.net.URL;
import org.apache.commons.io.IOUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;
public class voteHandler {
private static String SERVER = "";
private static String API_KEY = "";
public voteHandler(String SERVER_TO_SET, String API_KEY_TO_SET)
{
SERVER = SERVER_TO_SET;
API_KEY = API_KEY_TO_SET;
}
/*
Sends a GET request to RSPS Vote API.
RETURNS: a boolean
*/
public static boolean authenticate(String AUTH)
{
String url = generateURL(AUTH);
try {
String getJSON = IOUtils.toString(new URL(url));
JSONObject message = (JSONObject) JSONValue.parseWithException(getJSON);
String messageData = (String) message.get("MESSAGE");
System.out.println(messageData);
int responseData = Integer.parseInt((String) message.get("RESPONSE"));
System.out.println(responseData);
if(responseData == 5)
return true;
} catch (IOException | ParseException e) {
e.printStackTrace();
}
return false;
}
public static boolean getReward(String AUTH)
{
String url = generateURL(AUTH);
return false;
}
/*
Generates the url to the API
RETURNS: a String
*/
private static String generateURL(String AUTH)
{
String URL = "http://rspsvote.com/widget/api.php?"
+ "action=check"
+ "&server=" + SERVER
+ "&key=" + API_KEY
+ "&auth=" + AUTH;
return URL;
}
}
Testing class
import voteHandler.Org.RSPSVote.voteHandler;
public class testing {
public static void main(String args[])
{
voteHandler vote = new voteHandler("l6DZw", "ELWXQ-MI4BC-3K1RT-VUKPT-DGL2U");
vote.authenticate("Ptpz1n");
}
}
what's wrong with this JSON format being returned from the site?
http://rspsvote.com/widget/api.php?key=ELWXQ-MI4BC-3K1RT-VUKPT-DGL2U&action=check&auth=Ptpz1n&server=l6DZw
Also this is the error I get from eclipse:
Unexpected character (<) at position 63.
at org.json.simple.parser.Yylex.yylex(Yylex.java:610)
at org.json.simple.parser.JSONParser.nextToken(JSONParser.java:269)
at org.json.simple.parser.JSONParser.parse(JSONParser.java:118)
at org.json.simple.parser.JSONParser.parse(JSONParser.java:81)
at org.json.simple.parser.JSONParser.parse(JSONParser.java:75)
at org.json.simple.JSONValue.parseWithException(JSONValue.java:78)
at voteHandler.Org.RSPSVote.voteHandler.authenticate(voteHandler.java:34)
at testing.main(testing.java:8)
what's wrong with this JSON format being returned from the site?
It doesn't return JSON. The response's content type is text/html and the body contains
{"RESPONSE":"7","MESSAGE":"AUTHENTICATION WAS UNSUCCESSFUL."}
<!-- Hosting24 Analytics Code -->
<script type="text/javascript" src="http://stats.hosting24.com/count.php"></script>
<!-- End Of Analytics Code -->
You'll need to get rid of the XML or stop parsing after the JSON.
Look at the test code I have written below.
Using pure java I set an Authenticator and make a URI call to get some xml data and convert it to an object.
I wrote the code below to test performance of hotpotato (netty) vs. pure java (no pipelining).
The trouble is, I can't figure out how to Authenticate my request with hotpotato or netty, code for either is acceptable, I just want to test the performance diff (i.e. see how many requests will be performed in 5 seconds).
public static void main(String[] args) throws Exception {
Authenticator.setDefault(new MyAuthenticator("DummyUser", "DummyPassword"));
int timeToTestFor = 5000; //5 seconds;
int count = 0;
System.out.println("Start time");
long starttime = System.currentTimeMillis();
do {
URL url = new URL(
"http://example.com/rest/GetData.ashx?what=pizza&where=new%20york&visitorId=12345&sessionId=123456");
SearchResultsDocument doc = SearchResultsDocument.Factory.parse(url);
count++;
} while (System.currentTimeMillis() - starttime < timeToTestFor);
System.out.println("DONE Total count=" + count);
System.out.println("Netty/Hotpotatoe Start time");
count = 0;
starttime = System.currentTimeMillis();
do {
// Create & initialise the client
HttpClient client = new DefaultHttpClient();
client.init();
// Setup the request
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_0,
HttpMethod.GET, "/rest/GetData.ashx?what=pizza&where=new%20york&visitorId=12345&sessionId=123456");
// Execute the request, turning the result into a String
HttpRequestFuture future = client.execute("example.com", 80, request,
new BodyAsStringProcessor());
future.awaitUninterruptibly();
// Print some details about the request
System.out.println("A >> " + future);
// If response was >= 200 and <= 299, print the body
if (future.isSuccessfulResponse()) {
System.out.println("B >> "+future.getProcessedResult());
}
// Cleanup
client.terminate();
count++;
} while (System.currentTimeMillis() - starttime < timeToTestFor);
System.out.println("DONE Total count=" + count);
}
Here is working example of using basic authentication with Netty only. Tested with Jetty as a server requiring basic authentication.
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.base64.Base64;
import org.jboss.netty.handler.codec.http.DefaultHttpRequest;
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
import org.jboss.netty.handler.codec.http.HttpClientCodec;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.jboss.netty.util.CharsetUtil;
public class BasicAuthTest {
private static final int PORT = 80;
private static final String USERNAME = "";
private static final String PASSWORD = "";
private static final String URI = "";
private static final String HOST = "";
public static void main(String[] args) {
ClientBootstrap client = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
client.setPipelineFactory(new ChannelPipelineFactory() {
#Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("codec", new HttpClientCodec());
pipeline.addLast("aggregator", new HttpChunkAggregator(5242880));
pipeline.addLast("authHandler", new ClientMessageHandler());
return pipeline;
}
});
DefaultHttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, URI);
request.addHeader(HttpHeaders.Names.HOST, HOST);
String authString = USERNAME + ":" + PASSWORD;
ChannelBuffer authChannelBuffer = ChannelBuffers.copiedBuffer(authString, CharsetUtil.UTF_8);
ChannelBuffer encodedAuthChannelBuffer = Base64.encode(authChannelBuffer);
request.addHeader(HttpHeaders.Names.AUTHORIZATION, encodedAuthChannelBuffer.toString(CharsetUtil.UTF_8));
client.connect(new InetSocketAddress(HOST, PORT)).awaitUninterruptibly().getChannel()
.write(request).awaitUninterruptibly();
}
public static class ClientMessageHandler extends SimpleChannelHandler {
#Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
e.getCause().printStackTrace();
}
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
HttpResponse httpResponse = (HttpResponse) e.getMessage();
String json = httpResponse.getContent().toString(CharsetUtil.UTF_8);
System.out.println(json);
}
}
}
Using the ElementalHttpServer example class found here:
https://hc.apache.org/httpcomponents-core-4.3.x/httpcore/examples/org/apache/http/examples/ElementalHttpServer.java
I am able to successfully receive post data, my goal is to convert the received post data into a string I can print. I've modified the HttpFileHandler as follows, using eneity.getContent() to get the inputStream, but i'm not sure how I can convert the inputStream into a String.
static class HttpFileHandler implements HttpRequestHandler {
private final String docRoot;
public HttpFileHandler(final String docRoot) {
super();
this.docRoot = docRoot;
}
public void handle(
final HttpRequest request,
final HttpResponse response,
final HttpContext context) throws HttpException, IOException {
String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) {
throw new MethodNotSupportedException(method + " method not supported");
}
String target = request.getRequestLine().getUri();
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
byte[] entityContent = EntityUtils.toByteArray(entity);
InputStream inputStream = entity.getContent();
String str= inputStream.toString();
byte[] b3=str.getBytes();
String st = new String(b3);
System.out.println(st);
for(int i=0;i<b3.length;i++) {
System.out.print(b3[i]+"\t");
}
System.out.println("Incoming entity content (bytes): " + entityContent.length);
}
}
}
Thanks for any ideas
Here is simple console logging handler; it logs every request (not only POST) - both headers and payload:
package com.mycompany;
import org.apache.http.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.util.EntityUtils;
import org.omg.CORBA.Request;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Created by IntelliJ IDEA.
* User: Piotrek
* To change this template use File | Settings | File Templates.
*/
public class LoggingHandler implements HttpRequestHandler {
public void handle(HttpRequest httpRequest, HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException {
System.out.println(""); // empty line before each request
System.out.println(httpRequest.getRequestLine());
System.out.println("-------- HEADERS --------");
for(Header header: httpRequest.getAllHeaders()) {
System.out.println(header.getName() + " : " + header.getValue());
}
System.out.println("--------");
HttpEntity entity = null;
if (httpRequest instanceof HttpEntityEnclosingRequest)
entity = ((HttpEntityEnclosingRequest)httpRequest).getEntity();
// For some reason, just putting the incoming entity into
// the response will not work. We have to buffer the message.
byte[] data;
if (entity == null) {
data = new byte [0];
} else {
data = EntityUtils.toByteArray(entity);
}
System.out.println(new String(data));
httpResponse.setEntity(new StringEntity("dummy response"));
}
}
Registration of handler using org.apache.http.localserver.LocalTestServer (with ElementalHttpServer it is similar - you also have HttpRequestHandler implementation above):
public static void main(String[] args) throws Exception {
LocalTestServer server = new LocalTestServer(null, null);
try {
server.start();
server.register("/*", new LoggingHandler());
server.awaitTermination(3600 * 1000);
} catch (Exception e) {
e.printStackTrace();
} finally {
server.stop();
}
}