Jfreechart and jdbc.CategoryDataset - jdbc

My goal is to write a small program that reaches into our Public Safety database and retrieves ambulance response times. Then I want to take that data and generate a histogram.
I am having a very difficult time getting JFreechart to print a histogram of ambulance response times. When I run my code Netbeans generates an error message stating:
Exception in thread "main" java.lang.ClassCastException: org.jfree.data.jdbc.JDBCCategoryDataset cannot be cast to org.jfree.data.xy.IntervalXYDataset
at EMSResearch.histogram1.main(histogram1.java:39)
C:\Users\kulpandm\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 7 seconds)
I have absolutely no idea how to solve this issue. If I can get a histogram to print out I can then move on and hack away at making it look good for my reports. Shown below is my code:
package EMSResearch;
import java.io.File;
import java.io.IOException;
import java.sql.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.jdbc.JDBCCategoryDataset;
import org.jfree.data.xy.IntervalXYDataset;
public class histogram1
{
public static void main(String[] args) throws ClassNotFoundException
{
try
{
Connection conn = null;
conn = DriverManager.getConnection("jdbc:sqlserver://MyURL;database=MyDatabase;integratedsecurity=false;user=MyUser;password=MyPassword");
//dataset = new JDBCCategoryDataset(conn);
String query = "SELECT PUN_UnitID\n"
+ ", DATEDIFF(SECOND, IIU_tenroute, IIU_tArrive) AS [ResponseTime]\n"
+ "FROM IIncidentUnitSummary\n"
+ "WHERE IIU_tDispatch > 'may 15, 2016'\n"
+ "AND PUN_UnitID LIKE 'M[0-4]_'\n"
+ "AND IIU_tEnroute IS NOT NULL\n"
+ "AND IIU_tArrive IS NOT NULL\n"
+ "AND DATEDIFF(SECOND, IIU_tEnroute, IIU_tArrive) BETWEEN 0 AND 1800";
JDBCCategoryDataset dataset = new JDBCCategoryDataset(conn, query);
dataset.executeQuery(query);
conn.close();
//the following blows up.
JFreeChart chart;
chart = ChartFactory.createHistogram("data", "ws range", "freq", (IntervalXYDataset) dataset, PlotOrientation.VERTICAL, true, false, false);
int width = 560;
int height = 370;
File histChart = new File("c:\\histChart2.jpeg");
try
{
ChartUtilities.saveChartAsJPEG(histChart, chart, width, height);
} catch (IOException ex)
{
Logger.getLogger(chart2.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (SQLException ex)
{
ex.printStackTrace();
}
}
}
Can you please show me what I am doing incorrectly?
What can I do to fix this? (please be specific since I am not an expert programmer).

A CategoryDataset is not an IntervalXYDataset; they provide completely different things to clients.
A CategoryDataset can be used to create a bar chart. Invoking ChartFactory.createBarChart() using your JDBCCategoryDataset should at least give you something to see. Refer to this related example.
The API suggests "writing your own code to read data from a ResultSet." I'd use the data to populate a HistogramDataset, seen here. Because HistogramDataset implements IntervalXYDataset, it is suitable for use with ChartFactory.createHistogram(). Where the example has one series for each primary color, it looks like you might want one series for each PUN_UnitID.
Conceptually, it may be easier to SELECT DISTINCT PUN_UnitID that meet your LIKE clause in an initial query. Then query the response time values for each PUN_UnitID and invoke dataset.addSeries(PUN_UnitID, values, bins).
Alternatively, loop through the ResultSet, adding entries to a Map<String, List<Integer>>, where the key is the PUN_UnitID the value is aList of response times. Use the Map entries to construct the HistogramDataset as before.
If latency becomes a problem, update the dataset in using a SwingWorker, as shown here.

Related

Jackson XML "Undeclared general entity" caused by custom entity

I'm deserializing a large XML file (not mine) and it contains custom entities defined as:
<!ENTITY math "mathematics">
and elements used this way:
<field>&math;</field>
When I try to deserialize it by:
XmlMapper xmlMapper = new XmlMapper();
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
return xmlMapper.readValue(classloader.getResourceAsStream("file.xml"), MyClass.class);
I get this error:
com.fasterxml.jackson.databind.JsonMappingException: Undeclared general entity "math"
I think it might be a security measure to prevent Xml External Entity injections.
Is there a way to mark these custom entities as valid? Like create an Enum for them or something?
If not, is there a flag to just parse these as Strings?
Update:
I was able to work around this problem by basically doing a find-replace on the text file. It's quite an ugly solution and if anyone has a better idea, I'm all ears. :)
I know it may be a little late, but just in case someone else is stuck on the same issue:
You have to set a custom XMLResolver as XMLInputFactory's property:
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.ctc.wstx.api.WstxInputProperties;
import javax.xml.stream.XMLResolver;
import javax.xml.stream.XMLStreamException;
var xmlMapper = new XmlMapper();
xmlMapper.getFactory().getXMLInputFactory().setProperty(
WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER,
new XMLResolver() {
#Override
public Object resolveEntity(String publicId, String systemId, String baseUri, String ns) throws XMLStreamException {
// replace the entity with a string of your choice, e.g.
switch (ns) {
case "nbsp":
return " ";
default:
return "";
}
// some useful tool is org.apache.commons.text.StringEscapeUtils
// e.g.
// return StringEscapeUtils.escapeXml10(StringEscapeUtils.unescapeHtml4('&' + ns + ';'));
}
}
);
// then xmlMapper.readValue....

How does the POI Event API read data from Excel and why does it use less RAM?

I am currently writing my bachelor thesis and I am using the POI Event API from Apache. In short, my work is about a more efficient way to read data from Excel.
I get asked by developers again and again how exactly this is meant with Event API. Unfortunately I don't find anything on the Apache page about the basic principle.
Following code, how I use the POI Event API (This is from the Apache example for XSSF and SAX):
import java.io.InputStream;
import java.util.Iterator;
import org.apache.poi.ooxml.util.SAXHelper;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException;
public class ExampleEventUserModel {
public void processOneSheet(String filename) throws Exception {
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader( pkg );
SharedStringsTable sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
// To look up the Sheet Name / Sheet Order / rID,
// you need to process the core Workbook stream.
// Normally it's of the form rId# or rSheet#
InputStream sheet2 = r.getSheet("rId2");
InputSource sheetSource = new InputSource(sheet2);
parser.parse(sheetSource);
sheet2.close();
}
public void processAllSheets(String filename) throws Exception {
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader( pkg );
SharedStringsTable sst = r.getSharedStringsTable();
XMLReader parser = fetchSheetParser(sst);
Iterator<InputStream> sheets = r.getSheetsData();
while(sheets.hasNext()) {
System.out.println("Processing new sheet:\n");
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
System.out.println("");
}
}
public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException, ParserConfigurationException {
XMLReader parser = SAXHelper.newXMLReader();
ContentHandler handler = new SheetHandler(sst);
parser.setContentHandler(handler);
return parser;
}
/**
* See org.xml.sax.helpers.DefaultHandler javadocs
*/
private static class SheetHandler extends DefaultHandler {
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;
private SheetHandler(SharedStringsTable sst) {
this.sst = sst;
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// c => cell
if(name.equals("c")) {
// Print the cell reference
System.out.print(attributes.getValue("r") + " - ");
// Figure out if the value is an index in the SST
String cellType = attributes.getValue("t");
if(cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
}
// Clear contents cache
lastContents = "";
}
public void endElement(String uri, String localName, String name)
throws SAXException {
// Process the last contents as required.
// Do now, as characters() may be called more than once
if(nextIsString) {
int idx = Integer.parseInt(lastContents);
lastContents = sst.getItemAt(idx).getString();
nextIsString = false;
}
// v => contents of a cell
// Output after we've seen the string contents
if(name.equals("v")) {
System.out.println(lastContents);
}
}
public void characters(char[] ch, int start, int length) {
lastContents += new String(ch, start, length);
}
}
public static void main(String[] args) throws Exception {
ExampleEventUserModel example = new ExampleEventUserModel();
example.processOneSheet(args[0]);
example.processAllSheets(args[0]);
}
}
Can someone please explain to me how the Event API works? Is it the same as the event-based architecture or is it something else?
A *.xlsx file, which is Excel stored in Office Open XML and is what apache poi handles as XSSF, is a ZIP archive containing the data in XML files within a directory structure. So we can unzip the *.xlsx file and get the data directly from the XML files then.
There is /xl/sharedStrings.xml having all the string cell values in it. And there is /xl/workbook.xml describing the workbook structure. And there are /xl/worksheets/sheet1.xml, /xl/worksheets/sheet2.xml, ... which are storing the sheets' data. And there is /xl/styles.xml having the style settings for all cells in the sheets.
Per default while creating a XSSFWorkbook all those parts of the *.xlsx file will become object representations as XSSFWorkbook, XSSFSheet, XSSFRow, XSSFCell, ... and further objects of org.apache.poi.xssf.*.* in memory.
To get an impression of how memory consuming XSSFSheet, XSSFRow and XSSFCell are, a look into the sources will be good. Each of those objects contains multiple Lists and Maps as internally members and of course multiple methods too. Now imagine a sheet having hundreds of thousands of rows each containing up to hundreds of cells. Each of those rows and cells will be represented by a XSSFRow or a XSSFCell in memory. This cannot be an accusation to apache poi because those objects are necessary if working with those objects is needed. But if the need is really only getting the content out of the Excel sheet, then those objects are not all necessary. That's why the XSSF and SAX (Event API) approach.
So if the need is only reading data from sheets one could simply parsing the XML of all the /xl/worksheets/sheet[n].xml files without the need for creating memory consuming objects for each sheet and for each row and for each cell in those sheets.
Parsing XML in event based mode means that the code goes top down through the XML and has callback methods defined which get called if the code detects the start of an element, the end of an element or character content within an element. The appropriate callback methods then handle what to do on start, end or with character content of an element. So reading the XML file only means running top down through the file once, handle the events (start, end, character content of an element) and are able getting all needed content out of it. So memory consuming is reduced to storing the text data gotten from the XML.
XSSF and SAX (Event API) uses class SheetHandler which extends DefaultHandler for this.
But if we are already at this level where we get at the underlying XML data and process it, then we could go one more step back too. Native Java is able handling ZIP and parsing XML. So we would not even need additional libraries at all. See how read excel file having more than 100000 row in java? where I have shown this. My code uses Package javax.xml.stream which also provides using event based XMLEventReader but not using callbacks but linear code. Maybe this code is simpler to understand because it is all in one.
For detecting whether a number format is a date format, and so the formatted cell contains a date / time value, one single apache poi class org.apache.poi.ss.usermodel.DateUtil is used. This is done to simplify the code. Of course even this class we could have coded our self.

Log all methods called in an app by Xposed

As title said, I want to use xposed to log all methods called in an app from it start till I stop it. I only want to log Class name, Method name, don't want to hook all method.
I try this code, but get error getMethod not found.
findAndHookMethod("java.lang.Class", lpparam.classLoader, "getMethod", String.class, Object.class, new XC_MethodHook()
Thanks in advance!
There is no one line solution like what you seem to be searching.
Hooking all methods will let log what methods were called by app from it start till stop (sort of - see below), but if (for some reason) you don't want to hook all methods, the only solution I can think of is modifying the java VM itself (NOT something I would recommend.)
A solution that (sort of) works
What I did was first use apktool to decompile my apk and get the names of all the methods in all the classes.
Then I used xposed to hook into every single method of every class and print to the dlog the current function name.
Why it only sort of works
Xposed has an overhead whenever it hook a methods. For general usage of xposed apps, it isnt much. But when you start hooking each and every methods of an app, the overhead very quickly becomes ridiculously large - So much so that while the above methods works for small apps, for any large app it very quickly causes the app to hang and then crash.
An alternative that also sort-of works
FRIDA is a way to inject javascript to native apps. Here they show you how to log all function calls. While in the above link they log all function calls in a piece of python code, the same code also works for Android.
There is a way to log all Java methods.Modify XposedBridge.
Xposed hook java method through XposedBridge.java's method
"handleHookedMethod(Member method, int originalMethodId, Object additionalInfoObj, thisObject, Object[] args)"
Log.v(TAG, "className " + method.getClass().getName() + ",methodName " + method.getName());
As mentioned before Xposed is not the way to go in this situation due to its overhead.
The simplest solution is just to use dmtracedump as provided by Google. Most x86 Android images and emulator come with the debuggable flag on (ro.debuggable) so you can even use it for closed source apps.
Additionally other tools such as Emma are known to work with Android as well, but these might need modifications to the source code.
I found a solution.
See this code snippet below.
package com.kyunggi.logcalls;
import android.content.pm.*;
import android.util.*;
import dalvik.system.*;
import de.robv.android.xposed.*;
import de.robv.android.xposed.callbacks.XC_LoadPackage.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import android.app.*;
public class Main implements IXposedHookLoadPackage {
private String TAG = "LogCall";
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.android.bluetooth")) {
Log.i(TAG, "Not: " + lpparam.packageName);
return;
}
Log.i(TAG, "Yes " + lpparam.packageName);
//Modified https://d3adend.org/blog/?p=589
ApplicationInfo applicationInfo = AndroidAppHelper.currentApplicationInfo();
if (applicationInfo.processName.equals("com.android.bluetooth")) {
Set<String> classes = new HashSet<>();
DexFile dex;
try {
dex = new DexFile(applicationInfo.sourceDir);
Enumeration entries = dex.entries();
while (entries.hasMoreElements()) {
String entry = (String) entries.nextElement();
classes.add(entry);
}
dex.close();
} catch (IOException e) {
Log.e("HookDetection", e.toString());
}
for (String className : classes) {
boolean obex = false;
if (className.startsWith("com.android.bluetooth") || (obex = className.startsWith("javax.obex"))) {
try {
final Class clazz = lpparam.classLoader.loadClass(className);
for (final Method method : clazz.getDeclaredMethods()) {
if (obex) {
if (!Modifier.isPublic(method.getModifiers())) {
continue; //on javax.obex package, hook only public APIs
}
}
XposedBridge.hookMethod(method, new XC_MethodHook() {
final String methodNam = method.getName();
final String classNam = clazz.getName();
final StringBuilder sb = new StringBuilder("[");
final String logstr = "className " + classNam + ",methodName " + methodNam;
#Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
//Method method=(Method)param.args[0];
sb.setLength(0);
sb.append(logstr);
//Log.v(TAG,logstr);
for (Object o : param.args) {
String typnam = "";
String value = "null";
if (o != null) {
typnam = o.getClass().getName();
value = o.toString();
}
sb.append(typnam).append(" ").append(value).append(", ");
}
sb.append("]");
Log.v(TAG, sb.toString());
}
});
}
} catch (ClassNotFoundException e) {
Log.wtf("HookDetection", e.toString());
}
}
}
}
// ClassLoader rootcl=lpparam.classLoader.getSystemClassLoader();
//findAndHookMethod("de.robv.android.xposed.XposedBridge", rootcl, "handleHookedMethod", Member.class, int.class, Object.class, Object.class, Object[].class, );
}
}

Run SQL script on JDBC connection, minimal approach

Long story short: I want to run a SQL script on an HSQLDB database.
I want to follow a minimalistic approach, which means:
Absolutely no manual parsing of SQL
No additional dependencies except for general Utilities. I make the distinction here because, for example I refuse to pull in Ibatis or Hibernate which are larger scope frameworks, but I will accept an apache commons or guava type utils library.
The library MUST BE AVAILABLE ON MAVEN. No small-time pet-project stuff.
(EDIT 12/5/15) Must have the ability to execute SQL file from classpath.
To give you some context:
try {
connection = DriverManager.getConnection("jdbc:hsqldb:file:mydb", "sa", "");
// Run script here
} catch (SQLException e) {
throw new RuntimeException("Unable to load database", e);
}
A one-liner would be great. Something like:
FancyUtils.runScript(connection, new File("myFile.sql"));
I did find org.hsqldb.persist.ScriptRunner but it takes a Database object as an argument and I can't seem to figure out how to get an instance. Also, I don't like the description of "Restores the state of a Database", so does that mean my database will be cleared first? That's definitely not what I want.
I just tried using the SqlFile object in SqlTool and it worked for me. The Maven dependency I used was
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>sqltool</artifactId>
<version>2.4.1</version>
</dependency>
The SQL script file I wanted to execute was "C:/Users/Public/test/hsqldbCommands.sql":
INSERT INTO table1 (id, textcol) VALUES (2, 'stuff');
INSERT INTO table1 (id, textcol) VALUES (3, 'more stuff');
and my Java test code was
package hsqldbMaven;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.hsqldb.cmdline.SqlFile;
public class HsqldbMavenMain {
public static void main(String[] args) {
String connUrl = "jdbc:hsqldb:file:C:/Users/Public/test/hsqldb/personal";
String username = "SA";
String password = "";
try (Connection conn = DriverManager.getConnection(connUrl, username, password)) {
// clear out previous test data
try (Statement st = conn.createStatement()) {
st.executeUpdate("DELETE FROM table1 WHERE ID > 1");
}
System.out.println("Before:");
dumpTable(conn);
// execute the commands in the .sql file
SqlFile sf = new SqlFile(new File("C:/Users/Public/test/hsqldbCommands.sql"));
sf.setConnection(conn);
sf.execute();
System.out.println();
System.out.println("After:");
dumpTable(conn);
try (Statement st = conn.createStatement()) {
st.execute("SHUTDOWN");
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
private static void dumpTable(Connection conn) throws SQLException {
try (
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT id, textcol FROM table1")) {
while (rs.next()) {
System.out.printf("%d - %s%n", rs.getInt("id"), rs.getString("textcol"));
}
}
}
}
producing
Before:
1 - Hello world!
After:
1 - Hello world!
2 - stuff
3 - more stuff
Edit: 2018-08-26
If you want to bundle your SQL script file into the project as a resource then see the example in the other answer.
Note also that this approach is not restricted to HSQLDB databases. It can be used for other databases as well (e.g., MySQL, SQL Server).
This uses the SqlTool library, but reads the script directly from the classpath by using the SqlFile class:
try(InputStream inputStream = getClass().getResourceAsStream("/script.sql")) {
SqlFile sqlFile = new SqlFile(new InputStreamReader(inputStream), "init", System.out, "UTF-8", false, new File("."));
sqlFile.setConnection(connection);
sqlFile.execute();
}
Even though iBatis was mentioned by the OP as a non-requirement, I still want to recommend MyBatis - the iBatis fork by the original creators.
The core library (org.mybatis:mybatis) requires no dependencies (all of its dependencies are optional) and while larger than HSQLDB SqlTool, at 1.7MB binary it is not horribly big for most uses and is continuously maintained (the last release, 3.5, was last month as of this writing).
You can initialize ScriptRunner with a JDBC Connection, then call runScript(new InputStreamReader(sqlinputst, Standard chartered.UTF_8)) to run whatever SQL script you can get an input steam of.

Key Input using GtkD

I'm a beginner of both gtk and GtkD.
Now, I'm trying to get input from keyboard with reference to this .
But, It seems that three years have made some changes in Toolkits.
I wrote code below. However, I got strange values of ev in callback function.
I could not see any prospect of resolution with going alone.
So, could you show me where to modify?
I appreciate you in advance, and also your patient with my poor English.
I'm using gtkD-2.1.1 and gtk+3.2.3.
this is the full code:
import std.stdio;
import gtkc.gdktypes;
import gtk.MainWindow;
import gtk.Widget;
import gdk.Event;
import gtk.Main;
class Window : MainWindow{
immutable width = 200;
immutable height = 200;
this(){
super("input test");
setDefaultSize(width,height);
setEvents(EventMask.KEY_PRESS_MASK); // Actually I don't know how this works
auto callback_func = cast(bool delegate(Event,Widget))&get_key; // I doubt this cast
this.addOnKeyPress(callback_func);
showAll();
}
bool get_key(GdkEventKey* ev, Widget widget){
writefln("sender %s", widget);
writefln("type %x",ev.type);
writefln("window* %x",ev.window);
writefln("send_event %x",ev.sendEvent);
writefln("time %x",ev.time);
writefln("state %x",ev.state);
writefln("keyval %x",ev.keyval);
writefln("length %x",ev.length);
writefln("gchar* %x",ev.string);
writefln("hardware_keycode %x",ev.hardwareKeycode);
writefln("group %x",ev.group);
writefln("is_modifier %x\n",ev.bitfield0);
return true;
}
}
void main(string[] args){
Main.init(args);
auto win = new Window();
Main.run();
}
Yes, that cast is wrong. I guess that Signature with GdkEventKey* is outdated. Change your get_key to take an Event and you should get proper results:
...
auto call = &get_key;
...
bool get_key(Event e, Widget widget){
GdkEventKey* ev = e.key();
...
I have never done anything with GtkD, and this is just the result of some glances over the docs. So, it's probably not best practice, but it should get you back on the road.

Resources