rs.next() returns false in java - java

the code is login there are entries in my database my also query is working fine but whenever i put any data valid or invalid it just shows email or pass incorrect my rs.next() just returns false. I also verified jdbc connection it works fine. Used mySql databse.
package bean;
import java.sql.*;
public class LoginDao {
public static boolean validate(LoginBean bean){
boolean status=false;
try{
Connection con=ConnectionProvider.getCon();
PreparedStatement ps=con.prepareStatement("select * from user432 where email=? and pass=?");
ps.setString(1,bean.getEmail());
ps.setString(2, bean.getPass());
ResultSet rs=ps.executeQuery();
status=rs.next();
}catch(Exception e){}
return status;
}
}

What it looks like to me is that all this method is meant to do is validate the actual existence of a particular User which contains the supplied E-Mail address and Password. Fair enough but you claim that you always get returned false from the method. The obvious reason for that would be the fact that your query found no results otherwise rs.next() would be true.
Well, it could be the extra curly bracket at the end of your method but let's just assume you just goofed there when copy/pasting the code into your post.
It could however be that bean.getEmail() and bean.getPass() are not supplying what you think it is, I don't know since we can't see the bean class. Maybe what you should try is bean.getEmail().toString() and bean.getPass().toString().
If your code is producing an actual Exception then you're hiding it by maintaining a empty catch block. There's a real good chance that an exception of some sort is thrown and therefore providing a false result from your method but you'll never know what it is since you have nothing in place to view it. You should really have the exception as a SQLException rather than just Exception but hey, that's not the end of the world, and within the catch block you should at least put something, maybe: System.out.println("What the....sumthin wrong with ma code!!!"); or even better yet: e.printStackTrace();.
Curious...is the Database Table name really user432? Or is that a User Name?

Related

Returning a ResultSet to another function [duplicate]

This question already has answers here:
Returning a ResultSet
(8 answers)
Closed 2 years ago.
I'm working on creating a program to manage a MySQL server. I have a working UI and code that can add new entries to the database as it should. Pictured below is the proto GUI that I'm using, the part that's important for the question is the table box that will show the entries of the database when it's working.
The code that I have for reading the contents of the database works as it should. The program is structured so that I have separate classes for the interface, scene controller and SQL commands. The issue that I'm dealing with is that I can pull the needed data from the database but getting to the scene controller class to write it to the database simply isn't working.
The relevant pieces of code are included below is included below.
SQL functions:
public ResultSet readDataBase() throws Exception{
try {
// Establish connection to server
Class.forName("com.mysql.cj.jdbc.Driver");
connect=DriverManager.getConnection("jdbc:mysql://localhost/library?"+"user=tempUser&password=12345");
statement=connect.createStatement();
// Execute query and write the results
resultSet=statement.executeQuery("select * from library.books");
return resultSet;
// writeResultSet(resultSet);
} catch (Exception e){
throw e;
} finally {
close();
}
}
Scene controller code:
public void fillTable() throws SQLException{
ResultSet resultSet=null;
try {
resultSet=commands.readDataBase();
while(resultSet.next()) {
String title = resultSet.getString("title");
String author = resultSet.getString("author");
String genre = resultSet.getString("genre");
String format = resultSet.getString("format");
String isbn = resultSet.getString("isbn");
System.out.println("Title: " + title);
System.out.println("Author: " + author);
System.out.println("Genre: " + genre);
System.out.println("Format: " + format);
System.out.println("ISBN: " + isbn);
System.out.println();
}
}catch (Exception e){
e.printStackTrace();
}
}
The purpose of the code in the scene controller block is simply to test for and read the result set for now. The code for writing to write the data from the result to their respective tables will be added later. This code was selected because I originally had it in the SQL functions class and it worked there, so I knew the code was good and did its job.
Whenever I run the code however, I get this error result.
java.sql.SQLException: Operation not allowed after ResultSet closed
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63)
at com.mysql.cj.jdbc.result.ResultSetImpl.checkClosed(ResultSetImpl.java:445)
at com.mysql.cj.jdbc.result.ResultSetImpl.next(ResultSetImpl.java:1726)
at library.test.windows.interfaceSceneController.fillTable(interfaceSceneController.java:108)
at library.test.windows.winInterface.main(winInterface.java:33)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
I've done some reading into this prior but the only really relevant source of info I could find was in this post from over seven years ago. The answer for that question made reference to using JavaBeans as a place to put the information as an in-between but then used a class called a 'Biler' in their sample code. I can't find any reference to a Biler anywhere except his post and my IDE (IntelliJ if that's relevant) did not recognize it at all. I've been doing some experimentation with JavaBeans but I'm not sure it solving my problem.
In summary, my question is this. What do I need to do in order to properly pass a ResultSet from the function accessing the SQL server to the class containing the code for writing it to the table in my interface? I know this must be possible somehow but I can't seem to figure it out.
Your database access code should be kept entirely separate from your user-interface code. The UI should not deal with an active ResultSet.
You need to copy the data out of the result set, or use a utility to do so for you.
CachedRowSet
A RowSet may be the solution. This interface extends ResultSet. See the Java Tutorials by Oracle for explanations.
You could use the CachedRowSet interface that keeps a copy of the result set data in memory, detached from the database. Oracle provides an implementation, as might other vendors such as your JDBC driver.
A CachedRowSet implementation is disconnected from the database. In contrast, a ResultSet maintains a database connection (the root of your problem). To quote the Javadoc:
A CachedRowSet object is a container for rows of data that caches its rows in memory, which makes it possible to operate without always being connected to its data source. Further, it is a JavaBeansā„¢ component and is scrollable, updatable, and serializable.
That interface is extended by a few more interfaces.
POJOs
Plain old Java objects is another option, copying every field of every row from your ResultSet into properties of a Java object.
You can simply loop the result set while instantiating records. Or you can use any of a variety of frameworks to assist.
Records
Defining a class for such POJOs is much simpler when using the new records feature arriving in Java 16, now previewed in Java 15. The constructor, getters, toString, and equals & hashCode are all synthesized by the compiler. You simply declare the properties.
A record can be declared as a stand-alone class, or as a nested class, or even locally within a method.
Well, I assume you are closing the conneciton in your close() method. So that's why it is closed. The finally is executed after the method body but before the result is passed to the calling funtion.
try {
return resultSet;
} finally {
close();
}
IMHO it is a bad pratice to pass back a resultset anyway because the resultset is not really typesafe. If you change the query you will break the fillTable() function without noticing. And, of course, you would need to find a way to close the resultset and the underlying DB connection at some point. This might be challenging.

Cross scripting error on the Retrieved Database data

I see a Cross Scripting injection error on the statement that follows the execute update. How do I sanitize the output to rid it of Cross scripting errors..
I have a simple code snippet which uses PreparedStatement to run a select and returns the values which is retrieved on the front end GUI screen.
XSS Flaw message:"The tainted data originated from an earlier call to java.sql.ResultSetMetaData.getColumnName. "
Java code:
Connection conn = null;
Statement stmt = null;
PreparedStatement pstmt = null;
try {
List alist= new ArrayList();
pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
int count = rs.getMetaData().getColumnCount();
for (int i = 1; i <= count; i++) {
alist.add(rs.getMetaData().getColumnName(i)) //Flaw seems to point to this.
}
}catch(Exception e){
//close connections
}
return alist;
Full Veracode Flaw:
Attack Vector: javax.servlet.jsp.JspWriter.print
Number of Modules Affected: 1
Description: This call to javax.servlet.jsp.JspWriter.print() contains a cross-site scripting (XSS) flaw. The application populates the HTTP response with untrusted input, allowing an attacker to embed malicious content, such as Javascript code, which will be executed in the context of the victim's browser. XSS vulnerabilities are commonly exploited to steal or manipulate cookies, modify presentation of content, and compromise confidential information, with new attack vectors being discovered on a regular basis. The first argument to print() contains tainted data from the variable getHtml(). The tainted data originated from an earlier call to java.sql.ResultSetMetaData.getColumnName. The tainted data is directed into an output stream returned by javax.servlet.jsp.JspWriter.
I don't know why a ResultSetMetaData object is calling a servlet method, but if I do understand it correctly it is used to print something in the servlet. But because all the data in your ResultSetMetaData is comming from your database's meta data (which can't possibly include javascript code or other XSS riscs) it should be save in this case.
ResultSetMetaData is a common used class (and used sinze a long time) so I realy don't think that this is a problem in current java versions.
So I'm not shure how to fix this, but I'm pretty shure that this is not a problem, because it's not possible to add any maleware code (javascript or sql injection code) in the metadata of your database.
So, I was finally able to figure out the problem.
My Query was:
SELECT COLUMN_A, COLUMN_A||'-'||COLUMN_B FROM SOME_TABLE WHERE COLUMN_C IS NULL;
There are a few things I did...
1) Add an alias name to my column and used rs.getMetaData().getcolumnlabel(i) instead of rs.getMetaData().getColumnName(i). This makes sure to eliminate pipeline or hyphens from the output resultset name.
2) Used OWASP's ESAPI.encoder().encodeForHTML(unsafeString) instead of using Encode.forHtml(escapeHtml) and StringEscapeUtils.escapeHtml(escapeHtml) on the variable passed to the prepared statement.
Ouput behavior of || and - when passing them through the various escape functions.
Input: String unsafeString ="<'HELLO'-||>";
Outputs:
Encode.forHtml(unsafeString) is <'HELLO'-||>
StringEscapeUtils.escapeHtml(unsafeString) is <'HELLO'-||>
ESAPI.encoder().encodeForHTML(unsafeString) is <'HELLO'-||>
ESAPI.encoder().decodeForHTML(safeString from above line) is <'HELLO'-||>
If the Output is sent to the jsp to be rendered back on the html then you dont have to do the decodeStep..

Returning Null vs Exception vs Contract

What would be considered an acceptable way of dealing with returning a record from a DB with the following 3 potential outcomes:
Db connection works, finds a user and returns a populated user object
Db connection works, doesn't find a user, returns a new user object
Db connection/query fails...
I'm for the most part aiming for design by contract:
class Scratch {
public User getUser(int id) {
try {
// Prepare SQL Query
PreparedStatement s = this.connection.prepareStatement(
"select * from get_user(?)"
);
// Provide SQL Parameters
s.setInt(1, id);
// Run our SQL
ResultSet rs = s.executeQuery();
rs.next();
// Extract data into Entity
User user = User.createFromDatabase(rs);
rs.close();
return user;
} catch(Exception e) {
e.printStackTrace();
}
return new User();
}
}
In the situation that the DB connection or query fails it's a little less obvious what I should do, I have a few options:
Return a new user object, because our method has agreed to return a user
Pro: This sticks to designing by contracts
Con: This makes it look like the user doesn't exist.
Return null since it didn't actually get a user.
Pro: This is totally clear that a user was not found
Con: Requires a null check
Throw an exception further up the chain.
Pro: Makes it explicitly clear the operation wasn't achieved
Con: Does not attempt to rectify issues where they happen
I'm leaning towards handling Exceptions as it avoids the billion-dollar mistake, and also maintains design by contract in normal situations.
However I'd like to know if there are any obvious pitfalls or if this is a familiar situation with a well established pattern to resolve it.
I would throw an exception and let the user know that the connection failed. Returning NULL is something I would never do because you won't know what the problem was.
I don't know why you would return "New user object" if you don't have connection to the database. You won't be able to save the user.
My choice will be to Throw an exception
Use Optional (please). This make explicit that the user could not be found in the database and avoid NullPointerException's.
Optional(User) if the user is found in the database
Empty if user is not found
If there is an Error you have two options:
Notify the client so it can get feedback and react to this failure. In this case throw an exception and handle it in the proper layer. This should be the default behaviour for most of the applications.
Hide it to the client, this is less common but some times the client doesn't care or you don't want to publish your failures. In that case just return an Empty.

Java: Cached RowSet insertRow fails: SQLException

So I'm trying to understand how to use the RowSet API, specifically CachedRowSet, and I feel like I've been bashing my head against a wall for the last hour or so and could use some help.
I've got some very simple tables set up in a MySQL database that I'm using to test this. I should also add that everything I'm attempting to do with RowSet I've been able to do successfully with ResultSet, which leads me to believe that the issue is with my usage of the ResultSet API, rather than the operation I'm attempting to do itself.
Anyway, I'm trying to insert a new row using ResultSet. I'll paste my code here, then add some notes about it below:
CachedRowSet rowSet = null;
try {
RowSetFactory rsFactory = RowSetProvider.newFactory();
rowSet = rsFactory.createCachedRowSet();
rowSet.setUrl("jdbc:mysql://localhost:3306/van1");
rowSet.setUsername("####");
rowSet.setPassword("####");
rowSet.setKeyColumns(new int[]{1});
} catch (SQLException e) {
e.printStackTrace();
}
String query = "select * from phone";
try {
rowSet.setCommand(query);
rowSet.execute();
printTable(rowSet);
rowSet.moveToInsertRow();
rowSet.setInt(1, 4);
rowSet.setString(2, "Mobile");
rowSet.setString(3, "1");
rowSet.setString(4, "732");
rowSet.setString(5, "555");
rowSet.setString(6, "1234");
rowSet.setString(7, "");
rowSet.insertRow();
rowSet.moveToCurrentRow();
rowSet.acceptChanges();
printTable(rowSet);
} catch (SQLException e) {
e.printStackTrace();
}
So, as you can see, I'm trying to update a table of phone numbers with a new phone number. Here are the details:
1) All the phone number fields are datatype char, so that leading zeroes are not lost.
2) I'm using the default CachedRowSet implementation provided by the JDBC API, as opposed to anything specific from the MySQL driver. Not sure if that matters or not, but I'm putting it here just in case. Also, I didn't see an option to import CachedRowSet from the driver library anyway.
3) I'm setting a value for every column in the table, because the RowSet API doesn't allow for rows to be inserted without a value for every column.
4) I've tried the operation using both the setter methods and the update methods. Same result either way.
5) As far as I can tell, I'm on the insert row when executing the insertRow() method. I also return to the current row before invoking acceptChanges(), but since my code never gets that far I can't really comment on that part.
6) The exception is a SQLException (no chained exception within it) thrown on the invocation of the insertRow() method. Here is the stack trace:
java.sql.SQLException: Failed on insert row
at com.sun.rowset.CachedRowSetImpl.insertRow(Unknown Source)
at firsttry.RowSetPractice.rowSetTest(RowSetPractice.java:87)
at firsttry.RowSetPractice.main(RowSetPractice.java:20)
So, I'm out of ideas. Any help would be appreciated. I've searched every thread on this site I could find, all I see is stuff about it failing on the acceptChanges() method rather than insertRow().

JDBC/Resultset error

My mysql-query in Java always stops (i.e. freezes and does not continue) at a certain position, which namely is 543,858; even though the table contains approx. 2,000,000 entries. I've checked this by logging the current result-fetching.
It is reproducible and happens every time at the very same position.
"SELECT abc from bcd WHERE DATEDIFF(CURDATE(), timestamp) <= '"+days+"'");
Addition: It definitely is a Java error, I've just tried out this statement in Navicat (50s running time).
The query seems to freeze after the log tells me that it's now adding the result of position 543,858.
try {
...
ResultSet res = new ResultSet();
PreparedStatement stmt = new PreparedStatement(); // prepare statmenet etc.
stmt.setFetchSize(Integer.MIN_VALUE);
res = stmt.executeQuery();
...
System.out.println(res.getStatement());
...
while (res.next())
treeSet.add(res.getString("userid"));
} catch (Exception e) {
e.printStackTrace();
}
Edit: We were able to figure out the problem. This method is fine and the returned result (500,000 instead of 2,000,000) is right as well (looked up in the wrong db to verify the amount); the problem was, that the next method-call that used the result of the one posted above takes literally forever, but had no logging-implemented. So I've been fooled by missing console-logs.
Thanks anyways!
I think you might be running out of memory after processing half a million records. Try assigning more memory using command line options -Xmx etc. See here for more info about command line options.
In mysql to use streaming ResultSets you have to specify more parameters, not only fetchSize.
Try:
stmt = conn.createStatement('select ...', java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
and see if that works.
It's documented in theĀ ResultSet section.
Strange that it doesn't throw exception, but this is the only suspect I have. Maybe it starts garbage collection/flushes memory to disk and it takes so much time it doesn't get to throw it.
I would try to add to your query " LIMIT 543857" and then " LIMIT 543857" and see what happens.
If the above does not help, use the limit directive combined with order by.
I suspect that there is invalid entry in your table and the way to find it is binary search.

Categories

Resources