I am developing a web service for e-commerce website, and i am returning all products based on some supplier_id from java into php client but it is giving me this error
Fatal error: Uncaught SoapFault exception: [soapenv:Server] Before start of result set in C:\wamp\www\eshop\viewProductsSupplier.php:194 Stack trace: #0 C:\wamp\www\eshop\viewProductsSupplier.php(194): SoapClient->__soapCall('viewProducts', Array) #1 {main} thrown in C:\wamp\www\eshop\viewProductsSupplier.php on line 194
I have tried to check whether the query executes or not but it is all fine
//php code
$soapclient = new SoapClient('http://localhost:8090/Eshop_ecommerce/services/Eshop_ecommerce?wsdl', ['trace' => 1]);
session_start();
$id=array('id'=>#$_SESSION['supplierId']);
$response=$soapclient->__soapCall("viewProducts",$id);
if (isset($response->Name))
{
print $response;
}
else
{
print "Data is null";
}
//Java code
ViewProductsResponse res = new ViewProductsResponse();
Class.forName(driver);
conn = DriverManager.getConnection(url,username,password);
stmt = conn.createStatement();
String Query=null;
String in=viewProducts.getViewProductsRequest();
if(!in.isEmpty())
{
Query="SELECT * FROM product";
}
else
{
Query="SELECT * FROM product WHERE product_supplier_id='"+viewProducts.getViewProductsRequest()+"'";
}
ProductArray pa=new ProductArray();
ResultSet result= stmt.executeQuery(Query);
//System.out.println(result);
while(result.next())
{
Product p= new Product();
//System.out.println(result.getString("product_id"));
p.setId(result.getString("product_id"));
p.setName(result.getString("product_name"));
p.setPrice(result.getString("product_price"));
p.setStock(result.getString("product_stock"));
String supplierNameQuery="SELECT supplier_id,supplier_name FROM supplier WHERE supplier_id='"+result.getString("product_supplier_id")+"'";
ResultSet resultSupplierName = stmt.executeQuery(supplierNameQuery);
p.setSupplierName(resultSupplierName.getString("supplier_name"));
String catQuery="SELECT * FROM product_category WHERE category_id='"+result.getString("product_category_id")+"'";
ResultSet resCat= stmt.executeQuery(catQuery);
p.setCategoryName(resCat.getString("category_name"));
pa.setProduct(p);
res.setProducts(pa);
}
//res.setViewProductsResponse("Data Entered");
return res;
where as i expect it to print all the resulting products
A ResultSet returned from Statement#executeQuery is positioned before the first row (see linked-in JavaDoc). In order for such ResultSet to point to the first row it needs re-positioned to it, for example using the next() method. This is done for the outer SELECT but not for the two inner ones. Further the return value from next() call needs to be checked in order to see if there is any row at all in that ResultSet.
This can be achieved for example like this:
if(resultSupplierName.next()) {
p.setSupplierName(resultSupplierName.getString("supplier_name"));
}
if(resCat.next()) {
p.setCategoryName(resCat.getString("category_name"));
}
Please note that the posted code has other open issues, for example the JDBC resources are not closed. I would strongly suggest to look either into JEE or Spring (giving that the code apparently runs in aplication server) or at least at this. Further is the code prone to SQL injection
Related
here my objective is to call a procedure over a database link in java. procedure takes one input and has got cursor as an output.
to check if my code is working properly, I created dummy procedure in my database and tried executing. it is working, able to get cursor and play with it.
however when i am calling some procedure over database link, getting error as
java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00201: identifier 'HR_CLICK_GET_EMP_DETAILS#IBSLUAT1.WORLD' must be declared
I had a call with developer who had created these procedure. according to him procedures exist at this end and access is already given to my user.
Now my questions and queries are
is there something different, i have to do while calling a procedure over database link(code is below)
what are the things i should be asking to sql developer. by the way database link is right.
String prc_name = "HR_CLICK_GET_CM_AND_ABOVE#IBSLUAT1.WORLD(?,?)";
String runSP = "{ call "+prc_name+" }";
String runSP1 = "{ call get_user_by_userId(?,?) }"; this one is working
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:#xx.xx.xxx.xx:port:SERVICE", "username", "password"); // uat
CallableStatement cs = conn.prepareCall(runSP);
cs.setString(1, "705151");
cs.registerOutParameter(2, OracleTypes.CURSOR);
cs.execute();
// get refcursor and convert it to ResultSet
ResultSet resultSet = (ResultSet) cs.getObject(2);
ResultSetMetaData rsmd = resultSet.getMetaData();
int columnCount = rsmd.getColumnCount();
System.out.println("Total Columns in ResultSet : "+columnCount);
System.out.println("Now Analyzing column one by one:\n\n-----------------------------------------------");
for (int i = 1; i <= columnCount; i++ ) {
String name = rsmd.getColumnName(i);
System.out.println("Column No:"+i+">>>>>>>>"+name);
}
}
catch(SQLException s)
{
s.printStackTrace();
}
catch(ClassNotFoundException s)
{
s.printStackTrace();
}
thanks in advance
Ashish
Try to use the Oracle user's name who owns the procedure as a prefix:
username.HR_CLICK_GET_EMP_DETAILS#IBSLUAT1.WORLD
Answer is "synonym".
SQL Developer has created a synonym for HR_CLICK_GET_EMP_DETAILS as HR_CLICK_GET_EMP_DETAILS#IBSLUAT1.WORLD
that is what he informed me, I could not quite wrap my head around that but able to hit the procedure.
but now , able to get get the metadata of a result set but unable to traverse rows.
I'm getting an error:
java.sql.SQLException: ORA-24338: statement handle not executed
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:743)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:207)
at oracle.jdbc.driver.T4CStatement.fetch(T4CStatement.java:1018)
at oracle.jdbc.driver.OracleResultSetImpl.close_or_fetch_from_next(OracleResultSetImpl.java:291)
at oracle.jdbc.driver.OracleResultSetImpl.next(OracleResultSetImpl.java:213)
at ashishtest.StoredProcedureCursor.main(StoredProcedureCursor.java:80)
I guess, new forum is required for this error.
also I am not marking this as solved as not sure how solution works.
Here is my stored procedure:
CREATE OR REPLACE PROCEDURE VIEWBROKERS
(o_username OUT USERS.USERNAME%TYPE)
AS
BEGIN
SELECT USERNAME
INTO o_username
FROM USERS
WHERE Role_ID = 3 ;
END VIEWBROKERS;
Here is my method calling the stored procedure:
public ResultSet pullBrokers() {
ResultSet rs = null;
try {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
con = DriverManager.getConnection(Messages.getString("OracleUserManagement.0"), Messages.getString("OracleUserManagement.1"), Messages.getString("OracleUserManagement.2")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
String storedProcedure = "{call VIEWBROKERS(?)}";
CallableStatement statement = con.prepareCall(storedProcedure);
statement.registerOutParameter(1, java.sql.Types.VARCHAR);
rs = statement.executeQuery();
con.commit();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
And lastly when I tried to print out the results:
public class TEST {
public static void main(String[] args) throws SQLException{
OraclePullListOfUsers pull = new OraclePullListOfUsers();
ResultSet rs = pull.pullBrokers();
try {
while (rs.next()){
System.out.println(rs.getString(1));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
I get the error message ORA-01422: exact fetch returns more than requested number of rows
Which is strange ,because there are only two rows of data in the table...
If someone could point me in the right the direction, that would be awesome!
Looks like you're problem is not related to Java, just on the SQL side. Could it be that both those two rows in the table have Role_ID=3?
The root cause for your problem:
ORA-01422: exact fetch returns more than requested number of rows
is that PL/SQL select into statement expects a query to match to exactly one row. If the query returns no rows or if the query return more than one row (as in your case) it will throw an exception.
You can't use select into to save the results to a single out variable if the query can return more than one row. Instead your subprogram should return a cursor (that is a pointer to a record set) that your Java component can query. Note that returning a cursor is not the only option, but in your case it looks like a good starting point.
This issue has been addressed several times in StackExchange universe. Please take a look e.g.
Return many rows on a plsql Oracle10g
How to return multiple rows from the stored procedure? (Oracle PL/SQL)
Calling Oracle PL/SQL stored procedure from java middle tier using JDBC on Linux?
A Java example Using Ref Cursors To Return Recordsets.
I would like to see only that products user is looking for them, but when second if is executed it will push(pointer or whatever is there) to next ID(id I have as unique so it will push to nowhere) and result is null. I hope you understand my problem :).
if (stmt.execute(
"SELECT * FROM products where ID=" + removeName)) {
rs = stmt.getResultSet();
if (!rs.next()) {
m = "ID not found.";
return m;
}
In your case, you can go for PreparedStatement for avoiding SQL-Injection problem.
PreparedStatement prodsQuery= con.prepareStatement("SELECT * FROM products where ID=?");
prodsQuery.setInt(1,removeName);
ResultSet rs = prodsQuery.executeQuery();
if(!rs.next())
{
m = "ID not found.";
return m;
}
The problem is that you're reading the first result in order to know if there's at least one result, then trying to consume the next results and missing the first one (adapted from your question description). I gave an explanation of how this works here.
A possible solution for this problem would be assuming the query executed with no problems and you have your results, then retrieve the data (or List of data) and as a last step verify if the data is not null or the List of data is not empty.
Code adapted from Naveen's answer to show the proposed solution
PreparedStatement prodsQuery =
con.prepareStatement("SELECT * FROM products where ID=?");
prodsQuery.setInt(1,removeName);
ResultSet rs = prodsQuery.executeQuery();
Assuming there's only one result to get:
//also assuming you will set the results in a Data class (yes, this can be replaced)
Data data = null;
if (rs.next()) {
//logic to retrieve data...
data = new Data();
data.setSomething(rs.get(1));
//more and more code to fill the data...
//because it looks that you need it as String (wonder why you return a String as well)
return data.toString();
}
//note: I use an else statement to check if indeed there were no results at all
//else statement added using a line separator for code explanation purposes
else {
m = "ID not found.";
return m;
}
Assuming there is a list of results to get:
//also assuming you will set the results in a Data class (yes, this can be replaced)
List<Data> dataList = new ArrayList<Data>();
while (rs.next()) {
//logic to retrieve data...
Data data = new Data();
data.setSomething(rs.get(1));
//more and more code to fill the data...
//because it looks that you need it as String (wonder why you return a String as well)
dataList.add(data);
}
//in this case, there's no validation in order to know if there's any result
//the validation must be in the client of this class and method checking if
//the result list is empty using if(!List#isEmpty) { some logic... }
return dataList;
First thing, your approach is vulnerable to SQL Injection. Please go for PreparedStatement.
Look at this simple example for using PreparedStatement
And you should do like this :
ResultSet rs = stmt.executeQuery("SELECT * FROM products where ID=" + removeName);
if (!rs.next()) {
m = "ID not found.";
return m;
}
I'm working on a project where the user is supposed to fill the criteria he wants in a form and then accordingly to these criteria a servlet returns the appropriate results from the the database; I'm using mysql server.
My problem is that the Prepared Statement I used for that (because the user can search with a variable number of criteria) always return null, so I get an
Exception: null java.lang.NullPointerException at
Servlet_GrowerResults.doGet(Servlet_GrowerResults.java:102)
Here's the method fetchGrowers in class GetData which returns the ResultSet to the Servlet_GrowerResults
private PreparedStatement stmt_growers=null;
private ResultSet rs_growers;
private final String getGrowersQuery="select * from grower where name like ? and surname like ? and area like ? and partnership like ?;";
public ResultSet fetchGrowers(String criteria_name,String criteria_surname,String criteria_area, String criteria_partnership){
try{
stmt_growers=dbcon.getConnection().prepareStatement(getGrowersQuery);
stmt_growers.setString(1, criteria_name);
stmt_growers.setString(3, criteria_surname);
stmt_growers.setString(5, criteria_area);
stmt_growers.setString(7, criteria_partnership);
rs_growers=stmt_growers.executeQuery();
return rs_growers;
}
catch(Exception e9){
errorMessage = "Error while getting all growers from database!<br>" + e9.getMessage();
return null;
}
here's the lines where ResultSets are initialized. There are also other else if to cover all the cases of criteria submited
try{
getData.getDBcon().open();
ResultSet rsAreas=getData.fetchGrowerAreas();
ResultSet rsPartnership=getData.fetchGrowerPartnership();
ResultSet rsGrowersReturned;
String sqlWildcard="%";
//Cases of criteria submited by the user,
//in order to send the apropriate parameters
//to the PreparedStatement
//1st case: searching without names criteria
if( (criteriaNames.length()>0) && (!(criteriaAreas.length()>0)) && (!(criteriaPartnerships.length()>0)) ){
rsGrowersReturned=getData.fetchGrowers(sqlWildcard,sqlWildcard,criteriaAreas,criteriaPartnerships);
}
and here's the lines where the Exception points. And more specificly line 102 is: while(rsGrowersReturned.next())
if((sorting.equals("περιοχή"))){
while(rsAreas.next()){
out.println("<table>");
String area=rsAreas.getString("area");
area = new String(area.getBytes("ISO-8859-1"), "ISO-8859-7");
out.println("<tr><th>"+rsAreas.getString("area")+"</th></tr>");
/*line 102*/ while(rsGrowersReturned.next()){
if(rsGrowersReturned.getString("area").equals(rsAreas.getString("area"))){
String name=rsGrowersReturned.getString("name");
name = new String(name.getBytes("ISO-8859-1"), "ISO-8859-7");
String surname=rsGrowersReturned.getString("surname");
surname = new String(surname.getBytes("ISO-8859-1"), "ISO-8859-7");
String partnership=rsGrowersReturned.getString("partnership");
partnership = new String(partnership.getBytes("ISO-8859-1"), "ISO-8859-7");
out.println("<tr><td>"+name+" "+surname+"</td>");
out.println("<td>"+partnership+"</td></tr>");
}//end of neaced if
}//end of second while
}//end of first while
out.println("</table>");
}//end of if
I can see that there occurs indeed the problem because before getting to the second while it prints the first area as it is supposed to do and then Exception!!!
I tried the sql query directly to the mysql server and it works, I just can't find the problem! Every answer will be appreciated, thank you.
You need to set the input parameters for your PrepareStatement in sequential order:
stmt_growers.setString(1, criteria_name);
stmt_growers.setString(2, criteria_surname);
stmt_growers.setString(3, criteria_area);
stmt_growers.setString(4, criteria_partnership);
I bet that an SQLException is swallowed here:
catch(Exception e9){
errorMessage = "Error while getting all growers from database!<br>" + e9.getMessage();
return null;
}
Fix that to either log the exception that occured or rethrow an appropriate higher level exception. Silently returning null on error is always a bad idea.
When you add the exception that occurs to your post, we could try and help you in tracking down the cause.
fetchGrowers has a suboptimal error handling. You are simply catching the exception, creating an unused message and return null, which leads to a nullpointer later, and we dont know why. You should at least log something, better yet (re-)throw an exception.
I write a opration on java soap service to query the database and then show the data I have searched on client jsp page. However, I can't show it, the variable "rs" cannot change, I don't know why? could someone help me to find the troboule?
This is the opration i create on soap service:
#WebMethod(operationName = "query")
public String query(#WebParam(name = "parameter") String parameter) {
ResultSet rs;
try {
Connection con = data1.getConnection();
Statement statement = con.createStatement();
String QueryString;
QueryString = "SELECT * from stud where name= parameter";
rs = statement.executeQuery(QueryString);
while (rs.next()) {
System.out.println(rs.getInt(1) + " " + rs.getString(2) + "\n");
}
} catch (Exception ex) {
System.out.println("Unable to connect to batabase.");//TODO write your implementation code here:
}
//TODO write your implementation code here:
return null;
}
I'm not totally sure I understand your question. Maybe you mean that you can view the console output and this process that rs is an empty result set. You said rs cannot change, but you probable realize that rs stores the entire result set and you only assign it once, so it doesn't "change" if your code is working currently.
One obvious thing that is wrong is that parameter is a variable (in fact, a parameter!) But you include it inside the quotes as part of the query string. So regardless if the function input, you are searching the database for the name "parameter"