Why the INSERT query doesn't work in this HttpServer code - java

Im trying to make a little server for my homework.This is very simple project yet i cant insert some variables (which i took from the client ,in an object form ,through serialization ) into the database .
It shows no errors! That's what i find strange and also the client receive the response without problems.
my Server class is as the following :
package server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import org.ietf.jgss.Oid;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class Server {
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(3333), 0);
server.createContext("/", new MyHandler());
server.setExecutor(null); // creates a default executor
server.start();
}
static class MyHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
ObjectInputStream ios = new ObjectInputStream(t.getRequestBody());
final String url = "jdbc:mysql://localhost/httpServer";
final String user = "root";
final String password = "";
try {
Send oin = (Send) ios.readObject();
String response = "Kjo eshte nje pergjigje nga serveri! \n"
+ "Clienti me id "
+ oin.getId()
+ " dhe me emer "
+ oin.getName()
+ " ka pasur "
+ oin.getAmount()
+ "$ ne llogarine e tij ,por me pas ka terhequr "
+ oin.getPaid()
+ "$ nga llogaria \n"
+ "Kjo terheqe eshte ruajtur ne database dhe tani gjendja e re eshte "
+ (oin.getAmount() - oin.getPaid()) + "$ \n";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
int id = oin.getId();
String emri = oin.getName();
int amount = oin.getAmount();
int paid = oin.getPaid();
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(url, user,
password);
try {
Statement s = con.createStatement();
s.executeUpdate("INSERT INTO person VALUES ('" + id
+ "','" + emri + "','" + amount + "','" + paid
+ "')");
} catch (SQLException s) {
System.out
.println("Tabel or column or data type is not found!");
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
can you please help me ?
Or have any idea what the problem may is ?
Edit:
Maybe i am doing something wrong in the Client:
package server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
class Send implements Serializable {
// duhet te implementoje interfacin serizable ne menyre qe tja dergoj
// serverit
private static final long serialVersionUID = 1L;
public int getId() {
return id;
}
public int getAmount() {
return amount;
}
public int getPaid() {
return paid;
}
int id = 1;
int amount = 2000;
int paid = 800;
String name = "Andi Domi";
public String getName() {
return name;
}
}
public class Client {
public static void main(String[] args) throws Exception {
try {
URL url = new URL("http://localhost:3333");
HttpURLConnection s = (HttpURLConnection) url.openConnection();
s.setDoOutput(true);
s.setDoInput(true);
s.setRequestMethod("POST");
s.setUseCaches(false);
Send obj = new Send();
ObjectOutputStream objOut = new ObjectOutputStream(
s.getOutputStream());
objOut.writeObject(obj);
InputStream in = s.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
int c;
while ((c = br.read()) != -1) {
System.out.print((char) c);
}
objOut.close();
s.disconnect();
} catch (IOException ex) {
System.err.println(ex);
System.err.print("gabimi eshte ketu");
}
}
}

After your executeUpdate statement you need to do.
con.commit();
to save the transaction.
EDIT: Based on the chat discussion, we learned that the column named emri is actually Emri in the table and was throwing:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'emri' in 'field list'
Changing the name resolves the issue.
Now unrelated to your problem, you should be using a PreparedStatement instead and should be closing your connection and statement
try {
PreparedStatement s = con.prepareStatement("INSERT INTO person(id, emri, amount, paid) VALUES (?,?,?,?)");
s.setInt(1,id);
s.setString(2,emri);
s.setInt(3,amount);
s.setInt(4,paid);
int count = s.executeUpdate();
con.commit();
} catch(Exception e){
e.printStackTrace();
//something bad happened rollback
//any uncommitted changes
con.rollback();
} finally {
if (con != null) {
con.close();
}
}

first, use prepared statement[docs] to avoid from SQL INJECTION
String sql = "INSERT INTO person VALUES (?,?,?,?)";
PreparedStatement prest = con.prepareStatement(sql);
prest.setString(1,id);
prest.setString(2,emri); // or use setInt for integer
prest.setString(3,amount); // or use setInt for integer
prest.setString(4,paid);
prest.executeUpdate()
second, if the the number of values does not match the total number of columns in your table, it will also fail because you are using the implicit type of INSERT statement. To solve it, just supply the column names where you want the values should be stored, eg
String sql = "INSERT INTO person (col1, col2, col3, col4) VALUES (?,?,?,?)";

Related

Open CSV Performance to write data

I came through a link: https://github.com/hyee/OpenCSV which drastically improves the writing time of the JDBC ResultSet to CSV due to setAsyncMode, RESULT_FETCH_SIZE
//Extract ResultSet to CSV file, auto-compress if the fileName extension is ".zip" or ".gz"
//Returns number of records extracted
public int ResultSet2CSV(final ResultSet rs, final String fileName, final String header, final boolean aync) throws Exception {
try (CSVWriter writer = new CSVWriter(fileName)) {
//Define fetch size(default as 30000 rows), higher to be faster performance but takes more memory
ResultSetHelperService.RESULT_FETCH_SIZE=10000;
//Define MAX extract rows, -1 means unlimited.
ResultSetHelperService.MAX_FETCH_ROWS=20000;
writer.setAsyncMode(aync);
int result = writer.writeAll(rs, true);
return result - 1;
}
}
But the problem is I don't know how I can merge above into my requirement. As the link has many other classes involved which I am not sure what they do and if I even need it for my requirement. Still, I tried but it fails to compile whenever I enable 2 commented line code. Below is my code.
Any help on how I can achieve this will be greatly appreciated.
package test;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Date;
import com.opencsv.CSVWriter;
import com.opencsv.ResultSetHelperService;
public class OpenCSVTest1
{
static Connection con =null;
static Statement stmt = null;
static ResultSet rs = null;
public static void main(String args[]) throws Exception
{
connection ();
retrieveData(con);
}
private static void connection() throws Exception
{
try
{
Class.forName("<jdbcdriver>");
con = DriverManager.getConnection("jdbc:","<username>","<pass>");
System.out.println("Connection successful");
}
catch (Exception e)
{
System.out.println("Exception while establishing sql connection");
throw e;
}
}
private static void retrieveData(Connection con) throws Exception
{
try
{
stmt=con.createStatement();
stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
String query = "SELECT * FROM dbo.tablename";
rs=stmt.executeQuery(query);
CSVWriter writer = new CSVWriter(new BufferedWriter(new FileWriter("C:\\Data\\File1.csv")));
ResultSetHelperService service = new ResultSetHelperService();
/*** ResultSetHelperService.RESULT_FETCH_SIZE=10000; ***/ // to add
service.setDateTimeFormat("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println("**** Started writing Data to CSV **** " + new Date());
writer.setResultService(service);
/*** writer.setAsyncMode(aync); ***/ // to add
int lines = writer.writeAll(rs, true, true, false);
writer.flush();
writer.close();
System.out.println("** OpenCSV -Completed writing the resultSet at " + new Date() + " Number of lines written to the file " + lines);
}
catch (Exception e)
{
System.out.println("Exception while retrieving data" );
e.printStackTrace();
throw e;
}
finally
{
rs.close();
stmt.close();
con.close();
}
}
}
UPDATE
I have updated my code. Right now code is writing complete resultset in CSV at once using writeAll method which is resulting in time consumption.
Now what I want to do is write resultset to CSV in batches as resultset's first column will always have dynamically generated via SELECT query Auto Increment column (Sqno) with values as (1,2,3..) So not sure how I can read result sets first column and split it accoridngly to write in CSV. may be HashMap might help, so I have also added resultset-tohashmap conversion code if required.
import com.opencsv.CSVWriter;
import com.opencsv.ResultSetHelperService;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class OpenCSVTest1
{
static int fetchlimit_src = 100;
static Connection con =null;
static Statement stmt = null;
static ResultSet rs = null;
static String filename = "C:\\Data\\filename.csv";
static CSVWriter writer;
public static void main(String args[])
{
try
{
connection();
retrieveData(con);
}
catch(Exception e)
{
System.out.println(e);
}
}
private static void connection() throws Exception
{
try
{
Class.forName("<jdbcdriver>");
con = DriverManager.getConnection("jdbc:","<username>","<pass>");
System.out.println("Connection successful");
}
catch (Exception e)
{
System.out.println("Exception while establishing sql connection");
throw e;
}
}
private static void retrieveData(Connection con) throws Exception
{
try
{
stmt=con.createStatement();
String query = "SELECT ROWNUM AS Sqno, * FROM dbo.tablename "; // Oracle
// String query = "SELECT ROW_NUMBER() OVER(ORDER BY Id ASC) AS Sqno, * FROM dbo.tablename "; // SQLServer
System.out.println(query);
stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(fetchlimit_src);
System.out.println("**** Started querying src **** " + new Date());
rs=stmt.executeQuery(query);
System.out.println("**** Completing querying src **** " + new Date());
// resultset_List(rs); // If required store resultset(rs) to HashMap
writetoCSV(rs,filename);
/** How to write resultset to CSV in batches instead of writing all at once to speed up write performance ?
* Hint: resultset first column is Autoincrement [Sqno] (1,2,3...) which might help to split result in batches.
*
**/
}
catch (Exception e)
{
System.out.println("Exception while retrieving data" );
e.printStackTrace();
throw e;
}
finally
{
rs.close();
stmt.close();
con.close();
}
}
private static List<Map<String, Object>> resultset_List(ResultSet rs) throws SQLException
{
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();
while (rs.next())
{
Map<String, Object> row = new HashMap<String, Object>(columns);
for(int i = 1; i <= columns; ++i)
{
row.put(md.getColumnName(i), rs.getObject(i));
}
rows.add(row);
}
// System.out.println(rows.toString());
return rows;
}
private static void writetoCSV(ResultSet rs, String filename) throws Exception
{
try
{
writer = new CSVWriter(new BufferedWriter(new FileWriter(filename)));
ResultSetHelperService service = new ResultSetHelperService();
service.setDateTimeFormat("yyyy-MM-dd HH:mm:ss.SSS");
long batchlimit = 1000;
long Sqno = 1;
ResultSetMetaData rsmd = rs.getMetaData();
String columnname = rsmd.getColumnLabel(1); // To retrieve columns with labels (for example SELECT ROWNUM AS Sqno)
System.out.println("**** Started writing Data to CSV **** " + new Date());
writer.setResultService(service);
int lines = writer.writeAll(rs, true, true, false);
System.out.println("** OpenCSV -Completed writing the resultSet at " + new Date() + " Number of lines written to the file " + lines);
}
catch (Exception e)
{
System.out.println("Exception while writing data" );
e.printStackTrace();
throw e;
}
finally
{
writer.flush();
writer.close();
}
}
}
You should be able to use the OpenCSV sample, pretty much exactly as it is provided in the documentation. So, there should be no need for you to write any of your own batching logic.
I was able to write a 6 million record result set to a CSV file in about 10 seconds. To be clear -that was just the file-write time, not the DB data-fetch time - but I think that should be fast enough for your needs.
Here is your code, with adaptations for using OpenCSV based on its documented approach... But please see the warning at the end of my notes!
import com.opencsv.CSVWriter;
import com.opencsv.ResultSetHelperService;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Date;
import java.text.SimpleDateFormat;
public class OpenCSVDemo {
static int fetchlimit_src = 100;
static Connection con = null;
static Statement stmt = null;
static ResultSet rs = null;
static String filename = "C:\\Data\\filename.csv";
public static void main(String args[]) {
try {
connection();
retrieveData(con);
} catch (Exception e) {
System.out.println(e);
}
}
private static void connection() throws Exception {
try {
final String jdbcDriver = "YOURS GOES HERE";
final String dbUrl = "YOURS GOES HERE";
final String user = "YOURS GOES HERE";
final String pass = "YOURS GOES HERE";
Class.forName(jdbcDriver);
con = DriverManager.getConnection(dbUrl, user, pass);
System.out.println("Connection successful");
} catch (Exception e) {
System.out.println("Exception while establishing sql connection");
throw e;
}
}
private static void retrieveData(Connection con) throws Exception {
try {
stmt = con.createStatement();
String query = "select title_id, primary_title from imdb.title";
System.out.println(query);
stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(fetchlimit_src);
System.out.println("**** Started querying src **** " + new Date());
rs = stmt.executeQuery(query);
System.out.println("**** Completing querying src **** " + new Date());
// resultset_List(rs); // If required store resultset(rs) to HashMap
System.out.println();
String timeStamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date());
System.out.println("Started writing CSV: " + timeStamp);
writeToCsv(rs, filename, null, Boolean.FALSE);
timeStamp = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date());
System.out.println("Finished writing CSV: " + timeStamp);
System.out.println();
} catch (Exception e) {
System.out.println("Exception while retrieving data");
e.printStackTrace();
throw e;
} finally {
rs.close();
stmt.close();
con.close();
}
}
public static int writeToCsv(final ResultSet rs, final String fileName,
final String header, final boolean aync) throws Exception {
try (CSVWriter writer = new CSVWriter(fileName)) {
//Define fetch size(default as 30000 rows), higher to be faster performance but takes more memory
ResultSetHelperService.RESULT_FETCH_SIZE = 1000;
//Define MAX extract rows, -1 means unlimited.
ResultSetHelperService.MAX_FETCH_ROWS = 2000;
writer.setAsyncMode(aync);
int result = writer.writeAll(rs, true);
return result - 1;
}
}
}
Points to note:
1) I used "async" set to false:
writeToCsv(rs, filename, null, Boolean.FALSE);
You may want to experiment with this and the other settings to see if they make any significant difference for you.
2) Regarding your comment "the link has many other classes involved": The OpenCSV library's entire JAR file needs to be included in your project, as does the related disruptor JAR:
opencsv.jar
disruptor-3.3.6.jar
To get the JAR files, go to the GitHub page, click on the green button, select the zip download, unzip the zip file, and look in the "OpenCSV-master\release" folder.
Add these two JARs to your project in the usual way (depends on how you build your project).
3) WARNING: This code runs OK when you use Oracle's Java 8 JDK/JRE. If you try to use OpenJDK (e.g. for Java 13 or similar) it will not run. This is because of some changes behind the scenes to hidden classes. If you are interested, there are more details here.
If you need to use an OpenJDK version of Java, you may therefore have better luck with the library on which this CSV library is based: see here.

Convert Java stringbuilder to CLOB and giveoutput as CLOB

i am trying to connect to teradata and execute a statement and reading the data using stringbuilder. I want the get this as output when i define the outparameter as string the output is getting truncated as it is greater than 50K characters, i want this to be coverted as CLOB and give me the output as CLOB, could some one please help me how i can achieve this.
here is the code i am using ..
import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.util.*;
import java.sql.*;
public class getDDLinfo {
public static void getDDL (int [] status, String objectType, String objName, String [] ddl)
throws SQLException {
ddl[0] = "Unknown failure in XSP.";
status[0] = 1;
Connection conn = DriverManager.getConnection("jdbc:default:connection");
try {
String sql = "show " + objectType + " " + objName + ";";
PreparedStatement stmt = conn.prepareStatement(sql);
StringBuilder result = new StringBuilder();
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
result.append(rs.getString(1));
result.append("\n");
}
if (result.length() > 0) {
ddl[0] = result.toString();
}
rs.close();
stmt.close();
conn.close();
status[0] = 0;
} catch (SQLException e) {
status[0] = e.getErrorCode();
ddl[0] = e.getMessage();
}
}
public static String toHexString(byte[] ba)
{
StringBuilder str = new StringBuilder();
for(int i = 0; i < ba.length; i++)
str.append(String.format("%x ", ba[i]));
return str.toString();
}
}

MySQL lag on get (SELECT)

My problem is that there is update troo at the get level so the server starts to lag 70% tps loss I do not know how to optimize its?
public static int getCoins(Player player) {
try {
PreparedStatement q = Main.sql.prepareStatement("SELECT Coins FROM Players WHERE Players_UUID = ?");
q.setString(1, player.getUniqueId().toString());
int coins= 0;
ResultSet rs = q.executeQuery();
while(rs.next()){
balance = rs.getInt("Coins");
}
q.close();
return coins;
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
You don't need to do a sql query every time to get coins, just create a int or hashmap field with the data and check every X time if data has changed.
if it has changed send update to mysql server and mark that data has saved like two hashmap/int fields.
hashmap1 = database data
hashmap2 = server data
if hashmap1 and hashmap2 are same don't update.
Do the update in async function like schedulerAsync or thread.
Here a similar example:
package test;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.entity.Player;
import org.bukkit.entity.Zombie;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import com.mysql.jdbc.Connection;
public class Event extends JavaPlugin implements Listener {
// Mysql update data
public static ConcurrentHashMap<UUID, Integer> player_zombiekills = new ConcurrentHashMap<UUID, Integer>();
// Mysql connection data
public static Connection connection;
private String host = "localhost";
private String database = "DB";
private String username = "user";
private String password = "123";
private int port = 3306;
//Kill zombie event
#EventHandler
public void zombieDeath(EntityDeathEvent eve) {
if (!(eve.getEntity() instanceof Zombie)) return; // Stop if death is not zombie
if (!(eve.getEntity().getKiller() instanceof Player)) return; // Stop if killer is not player
UUID uid = eve.getEntity().getKiller().getUniqueId(); // Save player uuid
if (player_zombiekills.contains(uid)) player_zombiekills.put(uid, 0); // Set kills 0 if not exist in hashmap
player_zombiekills.put(uid, player_zombiekills.get(uid) + 1); // plus 1 kills value
}
//On enable connection
public void onEnable() {
try {
if (connection != null && !connection.isClosed()) return;
Class.forName("com.mysql.jdbc.Driver");
connection = (Connection) DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database, username, password);
if (!connection.isClosed()) System.out.println("[MySQL] " + "Connected to '" + database + "'");
} catch (Exception e) {
System.err.println("[MySQL] " + e.getMessage());
}
new BukkitRunnable() {
public void run() {
// for updates
for (Entry<UUID, Integer> ent : player_zombiekills.entrySet()) {
try {
// send update
connection.createStatement().executeUpdate("UPDATE `tablename` SET `zombiekills`=`zombiekills`+" + ent.getValue() + " WHERE `uuid`='" + ent.getKey().toString() + "'");
// Sucess remove entry from hashmap to reset kills
player_zombiekills.remove(ent.getKey());
} catch (SQLException e) { // If error
System.err.println("[MySQL] " + e.getMessage()); // Print error in console
}
}
}
}.runTaskTimerAsynchronously(this, 20, 20 * 60 * 10); // Run async loop every 10 minutes
}
}
I do not see how to do because if you change the data in BDD it does not change on the server so if I do not get every 1 second its will not work so I have optimized with an async but how without return To get the coins...

SQLException Operation not allowed after ResultSet closed

I am attempting to write a JUnit test for a query which is retrieved via a textbox in an html form. The text retrieval has been tested and works but my unit test is failing. I am using 2 relevant classes: QueryController and QueryControllerTest. I have been playing around with when and what I am closing in these two classes and keep getting the error: Operation not allowed after ResultSet closed.
QueryControllerTest.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import static org.junit.Assert.*;
public class QueryControllerTest {
#Test
public void testQuery() {
ResultSet testRs = null;
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String connectionUrl = "jdbc:mysql://localhost:3306/test";
String connectionUser = "root";
String connectionPassword = "GCImage";
conn = DriverManager.getConnection(connectionUrl,
connectionUser, connectionPassword);
Query testQuery = new Query();
testQuery
.setQuery("select * from service_request where FN_contact = 'Greg'");
testRs = QueryController.executeSelect(conn, testQuery);
assertEquals("Laughlin", testRs.getString("LN_contact"));
assertEquals("Hello World", testRs.getString("Notes"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
testRs.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
QueryController.java
import java.util.Map;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class QueryController {
#RequestMapping(value = "/query")
public String processRegistration(#ModelAttribute("query") Query query,
Map<String, Object> model) {
String queryString = query.getQuery();
if (queryString != null && !queryString.isEmpty()) {
System.out.println("query (from controller): " + queryString);
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String connectionUrl = "jdbc:mysql://localhost:3306/test";
String connectionUser = "root";
String connectionPassword = "GCImage";
conn = DriverManager.getConnection(connectionUrl,
connectionUser, connectionPassword);
if (queryString.toLowerCase().startsWith("select")) {
ResultSet rs = executeSelect(conn, query);
} else {
int rowsUpdated = executeUpdate(conn, query);
System.out.println(rowsUpdated + " rows updated");
}
} catch (Exception e) {
e.printStackTrace();
}
}
return "query";
}
public static ResultSet executeSelect(Connection conn, Query query) {
ResultSet rs = null;
Statement stmt = null;
try {
stmt = conn.createStatement();
rs = stmt.executeQuery(query.getQuery());
while (rs.next()) {
String id = rs.getString("ID");
String firstName = rs.getString("FN_Contact");
String lastName = rs.getString("LN_Contact");
String notes = rs.getString("Notes");
System.out.println("ID: " + id + ", First Name: " + firstName
+ ", Last Name: " + lastName + ", Notes: " + notes);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(rs!=null){
rs.close();
}
if(stmt != null){
stmt.close();
}
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return rs;
}
}
QueryController.executeSelect is calling rs.close(), but then your assertEquals in QueryControllerTest.testQuery are calling methods on testRS. As executeSelect is returning the resultset, closing it first doesn't make sense. Further, executeSelect is being passed the connection, so it shouldn't be closing that either (what happens if the caller wants to do two different selects on the same connection?).
I think the problem is because you are creating two connections. Try to only instantiate the connection of QueryController class for your test. You will need to provide the connection. After you store it in a variable to run the query.
Connection con = QueryController.getConnection ();

Cannot find place to insert finally block to get rid of the error: Insert Finally to complete TryStatement

I've tried several spots to insert the finally block but no matter what I try it ends up making the code worse.
Here is my code, the 4th to last ending curly bracket is the one giving me the error. Any thoughts?
package com.tunestore.action;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.action.DynaActionForm;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.owasp.validator.html.*;
import org.owasp.esapi.*;
public class DownloadAction extends Action
{
private static final Log log = LogFactory.getLog(DownloadAction.class);
public static String DB_URL;
static
{
if (System.getProperty("tunestore.db.location") != null)
{
DB_URL = "jdbc:derby://localhost:1527/" + System.getProperty("tunestore.db.location");
}
else
{
DB_URL = "jdbc:derby://localhost:1527/" + System.getProperty("user.home") + "/.tunestore";
}
System.setProperty("jdbc.tunestore.url", DB_URL);
}
public static Connection getConnection() throws Exception
{
log.info("Opening database at " + DB_URL);
Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
Connection conn = DriverManager.getConnection(DB_URL);
return conn;
}
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
throws Exception
{
DynaActionForm daf = (DynaActionForm)form;
String user = (String)request.getSession(true).getAttribute("USERNAME");
if(user != null)
{
Connection conn = null;
try
{
conn = DownloadAction.getConnection();
String sql2 = "SELECT ID FROM CD WHERE CD.BITS = ?";
PreparedStatement stmt2 = conn.prepareStatement(sql2);
stmt2.setString(1, request.getParameter("cd"));
ResultSet rs2 = stmt2.executeQuery();
rs2.next();
String sql = "SELECT COUNT(*) "
+ "FROM TUNEUSER_CD "
+ "WHERE TUNEUSER_CD.TUNEUSER = ? AND TUNEUSER_CD.CD = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, user);
stmt.setInt(2, rs2.getInt(1));
ResultSet rs = stmt.executeQuery();
rs.next();
int owned = rs.getInt(1);
if(owned == 1)
{
try
{
// Try to open the stream first - if there's a goof, it'll be here
InputStream is = this.getServlet().getServletContext().getResourceAsStream("/WEB-INF/bits/" + request.getParameter("cd"));
if (is != null)
{
response.setContentType("audio/mpeg");
response.setHeader("Content-disposition", "attachment; filename=" + daf.getString("cd"));
byte[] buff = new byte[4096];
int bread = 0;
while ((bread = is.read(buff)) >= 0)
{
response.getOutputStream().write(buff, 0, bread);
}
}
else
{
ActionMessages errors = getErrors(request);
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("download.error"));
saveErrors(request, errors);
return mapping.findForward("error");
}
}
catch (Exception e)
{
e.printStackTrace();
ActionMessages errors = getErrors(request);
errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("download.error"));
saveErrors(request, errors);
return mapping.findForward("error");
}
return null;
}
}
}
}
}
That bracket is the location where your outer try block ends. It has no catch block and no finally block, so you get an error. Just add one or the other immediately after the bracket, or remove the try if it's not needed.
You only have one catch block, but two trys. Add a catch block for the first try-catch and you should have your issue solved.
Edit: Why are you nesting try-catch in the first place? I don't believe there is any need to do so.

Categories