Ive encountered a little problem.
I made a json url checker that checks if a twitch.tv stream is either online or offline.
That one thing is handled in a seperate class TwitchLiveChecker.java.
Now i want to call that class with a timer all X minutes but somehow i dont understand how to call the class.
This is how i call it;
public void LiveChecker() {
TTtwl.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
try {
TwitchLiveChecker.startup(); *<- THIS Doesnt work :(*
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(TwitchLiveChecker.json);
System.out.println(TwitchLiveChecker.json);
}
}, 1000*10, 1000*10);
}
and this is my TwitchLiveChecker class File;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
import org.json.JSONException;
import org.json.JSONObject;
public class TwitchLiveChecker {
public static JSONObject json;
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONObject json = new JSONObject(jsonText);
return json;
} finally {
is.close();
}
}
public static void startup(String[] args) throws IOException, JSONException {
json = readJsonFromUrl("http://api.justin.tv/api/stream/list.json?channel="+MyBot.ownerchannel+"");
System.out.println(json.toString());
System.out.println(json.get("id"));
}
}
Im thankful for any hints or examples on what im doing wrong :D
You are not passing parameters to a method that requires them. Since TwitchLiveChecker.startup() doesn't use the args parameter, you should remove it. Your method signature should be public static void startup(), not public static void startup(String[] args)
Also, threads and static data (specifically your public static JSONObject json; don't mix well. Depending on what your thread pool is doing, you could have multiple threads writing to your static json object at the same time, corrupting the data in it.
Related
If I use the filepath directly in the class CtoJ it works.
If i pass it through the constructor it gives me a Nullpointer.
Well I do not know what I could add to make my problem any more clear.
Well if I use String path =""; it throws no such file or directory.
It seems like the constructor is not able to write the filepath into the path variable?
public class CSVReader {
public static void main(String[] args) {
CtoJ test = new CtoJ("/Users/peterg/Desktop/test.csv");
}
}
import org.json.CDL;
import org.json.JSONArray;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CtoJ {
private String path;
private StringBuilder content = new StringBuilder();
private String line;
private String stringtoJSON;
public CtoJ(String path) {
this.path = path;
}
{
try {
BufferedReader reader = new BufferedReader(new FileReader(path));
while ((line = reader.readLine()) != null) {
content.append(removeUnnecessaryQuotes(line));
content.append(System.lineSeparator());
}
stringtoJSON = content.toString();
JSONArray jsonArray = CDL.toJSONArray(stringtoJSON);
System.out.println(jsonArray);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static String removeUnnecessaryQuotes(String s) {
String withoutQuotes;
withoutQuotes = s.substring(0).replaceAll("\"", "");
withoutQuotes.substring(0).replaceAll("\"\"", "\"");
return withoutQuotes;
}
}
Here is some of the data I use, if u want to test it:
FID,OBJECTID,SHAPE,LAGE,GRILLPLATZ_ID,RESERVIERUNG,WEBLINK1,SE_ANNO_CAD_DAT
"GRILLPLATZOGD.6748,6748,POINT (16.465255884594104 48.19018769574157),""22., Donauinsel, ca. 350 Meter stromab der Steinspornbrücke (Inselmitte, Erdwall)"",15,ja,http://www.wien.gv.at/amtshelfer/umwelt/wasserbau/donauinsel/grillplatzreservierung.html,"
"GRILLPLATZOGD.6749,6749,POINT (16.48177464603615 48.183356069714286),""22., Neue Donau, linkes Ufer, zwischen Steinspornbrücke und Waluliso Brücke (bei km 5,1) (Dammbereich) "",16,ja,http://www.wien.gv.at/amtshelfer/umwelt/wasserbau/donauinsel/grillplatzreservierung.html,"
"GRILLPLATZOGD.6750,6750,POINT (16.460158556964053 48.177745677669925),""11., Donaukanal, Alberner Hafenzufahrtsstraße, Nähe Margetinstraße"",0,nein,http://www.wien.gv.at/umwelt/wald/freizeit/grillen/,"
you get the error because you accidentally used an instance initializer block in your Code. That is
class Foo {
//constructor
public Foo() {
System.out.println("Constructor");
}
//instance initializer Block
{
System.out.println("Instance Initializer");
}
}
Generally, this is okay, however, the initializer block is executed before the constructor is.
In your particular example
BufferedReader reader = new BufferedReader(new FileReader(path));
in the initializer block is dependent on the instantiation of path in the constructor. So as a quick fix just move the code from the initializer to the constructor and you shouldn't get any NullPointerException.
Unexpected character () at position 0.
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 net.ddns.coolpvp.Testing.main(Testing.java:22)
I was making a TCP Server on Java, it was receiving a json and it gave this error, but I checked and the first character is '{', how can I fix this? I have no clue. I would be very grateful if you could help meEDIT: The JSON is generated by .NET Framework in a C# Application and this is a JSON
{"Type":"level-info","LevelNumber":1}
This is how the C# Application is generating the JSON
Program.cs
using System;
using System.Text;
using System.Net.Sockets;
using System.IO;
namespace Testing
{
public static class Program
{
public static void Main(string[] args)
{
TcpClient client = new TcpClient();
client.Connect("localhost", 152);
StreamWriter writer = new StreamWriter(client.GetStream(), Encoding.UTF8) { AutoFlush = true };
writer.WriteLine(new RequestLevelInfo(1).ToJSONString());
client.Close();
Console.ReadKey(true);
}
}
}
RequestLevelInfo.cs
using System.Web.Script.Serialization;
namespace Testing
{
public class RequestLevelInfo
{
public string Type { get { return "level-info"; } }
public int LevelNumber { get; }
public RequestLevelInfo(int level)
{
LevelNumber = level;
}
public string ToJSONString()
{
return new JavaScriptSerializer().Serialize(this);
}
}
}
The Server is reading it using a BufferedReader using the readLine method
package testing;
import java.net.Socket;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class Testing {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket();
server.bind(new InetSocketAddress(InetAddress.getByName("localhost"), 152));
Socket client = server.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
String dataReceived = reader.readLine();
JSONObject json = (JSONObject)new JSONParser().parse(dataReceived);
System.out.println(json.toJSONString());
client.close();
server.close();
} catch (IOException ex) {
ex.printStackTrace(System.err);
} catch (ParseException ex) {
ex.printStackTrace(System.err);
}
}
}
The problem is in your C# code: it's sending incorrect JSON.
You are using the Encoding.UTF8 object. This object includes an invisible and unnecessary "byte order marker" character, which the Java JSON parser does not understand. JSON "must not" use a byte order mark character: JSON Specification and usage of BOM/charset-encoding
The solution is to create your own instance of UTF8Encoding. For example:
UTF8Encoding jsonEncoding = new UTF8Encoding(false);
StreamWriter writer = new StreamWriter(client.GetStream(), jsonEncoding) { AutoFlush = true };
Hello, I thought about your code and changed something, here is my code:
public static void main(String[] args) {
try {
BufferedReader bufferedReader = java.nio.file.Files.newBufferedReader(Paths.get("test.json"));
JSONObject data = (JSONObject) new JSONParser().parse(bufferedReader);
System.out.println(data.get("Type"));
} catch (Exception e) {
e.printStackTrace();
}
}
This is the content of the test.json File:
{"Type":"level-info","LevelNumber":1}
My output is: level-info
Please check if you really have org.json.simple.JSONObject, org.json.simple.parser.JSONParser and org.json.simple.parser.ParseException imported.
Not that you accidentally imported anything else.
Have fun, I hope I could help you!
EDIT
So, for me the error occurred with the following example:
public static void main(String[] args) {
try {
String string = "{name=Asel, number1=40.34, number2=29.343}";
JSONObject object = (JSONObject) new JSONParser().parse(string);
System.out.println(object.get("name"));
} catch (Exception e) {
e.printStackTrace();
}
}
But not with this:
public static void main(String[] args) {
try {
String string = "{\"name\":\"Asel\", \"number1\":\"40.34\", \"number2\":\"29.343\"}";
JSONObject object = (JSONObject) new JSONParser().parse(string);
System.out.println(object.get("name"));
} catch (Exception e) {
e.printStackTrace();
}
}
Therefore I wonder if your string that you really get from your TCP socket is exactly {"Type":"level-info","LevelNumber":"1"} and not something wrong liek this: {"Type"="level-info","LevelNumber"="1"}
To test it you could try to replace = with : in the string of TPC Socket and see if the error still occurs.
JSONObject json = (JSONObject)new JSONParser().parse(dataReceived.replace("=", ":"));
I create java program that load JSON file from url , I push json object to this url every 20 seconds I want the program to give notification when the JSON file updated here is my java code
package com.company;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.*;
import java.net.URL;
import java.nio.charset.Charset;
public class Main {
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public static JSONArray readJsonFromUrl(String url) throws IOException, JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONArray jsonArray = new JSONArray(jsonText);
return jsonArray;
} finally {
is.close();
}
}
public static void main(String[] args) throws IOException, JSONException {
JSONArray json = readJsonFromUrl("http://frozen-brook-16337.herokuapp.com/history.json");
for(int i=0;i<json.length();i++){
JSONObject jo=json.getJSONObject(i);
System.out.println(jo.get("data"));
}
}
}
How to make java program listen to JSON file update ?
You need to create a scheduler that executes your bit of code after every 20 seconds. There are multiple ways to achieve this.
A good robust way would be to use something like Quartz Scheduler
Or for a quick solution you can also create a Thread and have its run() method execute the code in a loop.
public class MyPush implements Runnable {
public void run() {
long twentySeconds = 20*1000L;
while(true) {
//execute your code
Thread.sleep(twentySeconds);
}
}
public static void main(String args[]) {
(new Thread(new MyPush())).start();
}
}
I try to create java program that read JSON from this url, the url contain JSON array that updated every 20 seconds here is my java program that listen to the url and print the last JSON object from the JSON file:
ListenTojson.java
package com.company;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.*;
import java.net.URL;
import java.nio.charset.Charset;
class ListenToJson implements Runnable {
public void run() {
long tenSeconds = 10*1000L;
while(true) {
try {
JSONArray json = readJsonFromUrl("http://frozen-brook-16337.herokuapp.com/history.json");
JSONObject jo=json.getJSONObject(json.length()-1);
System.out.println(jo.get("data"));
Thread.sleep(tenSeconds);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public static JSONArray readJsonFromUrl(String url) throws IOException, JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
JSONArray jsonArray = new JSONArray(jsonText);
return jsonArray;
} finally {
is.close();
}
}
}
Main.java
package com.company;
public class Main {
public static void main(String[] args){
(new Thread(new ListenToJson())).start();
}
}
The code run as I expected. The JSON file contains coordinate that keep updated every 10 seconds. I need to create map application that read the coordinate from the JSON and then show it on the map as marker, I use JavaFx library to create the map application, when I add the code above (ListenToJson.java) the program behave differently when I use JavaFX library it does not read the latest JSON file.
here is the code
public class Controller{
//some code
(new Thread(new ListenToJson())).start();
//some code
}
Controller.java
The full class that I try to update the UI using the ListenToJson() function is here https://github.com/kikirizki/mapapp/blob/master/src/main/java/com/delameta/vesselmap/Controller.java the line 526, thanks
whats wrong with my code, why the ListenToJson() function read the outdated JSON file ?
I found the solution myself, the problem is the mapjfx library (I use in the code) use cache to cache the map tile and then it cause to cache the JSON file too. The solution is simply disable the cache mechanism, just diable it at line 350, change
offlineCache.setActive(true);
to be
offlineCache.setActive(false);
I have a Jersey Web-Service that I need to parse some json data that was send along with a request.
#POST
#Path ("/authenticate")
#Produces (MediaType.APPLICATION_JSON)
public Response authenticate (#Context HttpServletRequest request)
{
try {
StringBuffer json = new StringBuffer ();
BufferedReader reader = request.getReader();
int line;
while ((line = reader.readLine()) != null)
{
json.append(line);
}
System.out.prinln (json);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return Response.ok().entity(json).build();
}//end authenticate method
This service generates the following Exception:
java.lang.IllegalStateException: getInputStream() has already been called for this request
I did some research that suggests a getReader and getInputStream cannot be called on the same request. Therefore, it seemed like a getInputStream instance is already called. How is this possible if I haven't made a explicit call to it? To solve this problem, I used the getInputStream method instead
try {
ServletInputStream reader = request.getInputStream();
int line;
while ((line = reader.read()) != -1)
{
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return Response.ok().entity().build();
With this approach, how can I use the int of bytes to get the json?
Seems like you're missing a #Consumes annotation. You realise you can just have a method;
#POST
#Path ("/authenticate")
#Consumes (MediaType.APPLICATION_JSON)
#Produces (MediaType.APPLICATION_JSON)
public Response authenticate (String entity) {
//entity contains the posted content
}
Without having to read the stream yourself? If you have a bean representing your consumed JSON , then you can just add it as a method param and jersey will automatically parse it for you;
#POST
#Path ("/authenticate")
#Consumes (MediaType.APPLICATION_JSON)
#Produces (MediaType.APPLICATION_JSON)
public Response authenticate (AuthBean auth) {
//auth bean contains the parsed JSON
}
class AuthBean {
private String username;
private String password;
// getters/setters
}
Example post;
{
"username" : "joe#example.com",
"password" : "super s3cret"
}
we can read from the HttpServletRequest only once, so we have to be using HttpServletRequestWrapper inside a filter before reading the request and use the wrapper for subsequent calls for multiple times..
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import com.dbs.bds.ingestion.util.MultiReadRequestWrapper;
import lombok.extern.slf4j.Slf4j;
#Slf4j
public class SessionValidationFilter implements Filter {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
try {
log.debug("inside filter");
HttpServletRequest httpServletRequest = new MultiReadRequestWrapper((HttpServletRequest) servletRequest);
filterChain.doFilter(httpServletRequest, servletResponse);
} catch (Exception ex) {
log.error("error inside filter:{}", ex.getMessage());
}
}
}
The below is the code for Wrapper which we used in above Filter.
import org.apache.commons.io.input.BoundedInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
public class MultiReadRequestWrapper extends HttpServletRequestWrapper {
private static final Logger LOG = LoggerFactory.getLogger(MultiReadRequestWrapper.class);
// We include a max byte size to protect against malicious requests,
//since this all has to be read into memory
public static final Integer MAX_BYTE_SIZE = 1_048_576; // 1 MB
private StringBuilder body;
public MultiReadRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = new StringBuilder("");
try (
InputStream bounded = new BoundedInputStream(request.getInputStream(), MAX_BYTE_SIZE);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(bounded));){
String line;
while ((line = bufferedReader.readLine()) != null) {
body.append(line);
}
} catch(Exception e) {
LOG.error(e.getMessage());
}
}
#Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.toString().getBytes());
return new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
#Override
public boolean isFinished() {
return byteArrayInputStream.available() == 0;
}
#Override
public boolean isReady() {
return true;
}
#Override
public void setReadListener(ReadListener readListener) {
//do nothing
}
};
}
#Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
Now expose the above filter as bean
#Bean(name = "sessionValidationFilter")
public Filter getSessionValidationFilter() {
return new SessionValidationFilter();
}
#SuppressWarnings({"rawtypes", "unchecked"})
#Bean
public FilterRegistrationBean sessionValidationFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(getSessionValidationFilter());
registration.addUrlPatterns("/v1/create/record");
registration.setName("sessionValidationFilter");
return registration;
}