CallableStatement never ends when it is executed for first time - java

I am currently working with ejb3, Java 1.8, jboss and oracle project. I am having a issue with CallableStatement. I have a procedure that is called when a CSV file is processed. When the procedure it called for the first time most of the time it never ends. But when a reuse the procedure again it work perfectly. Could you please give me any advice how to deal with this situation?
cStmt = prepareCall("{call CPRPA_TPT_PRICE_CALC.tpt_data_import(?,?)}");
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.Connection;
import java.util.HashMap;
import javax.persistence.EntityManager;
import org.hibernate.Session;
import org.hibernate.engine.spi.SessionImplementor;
public abstract class ProcDao extends BaseDao {
/** Callable statement cache */
private HashMap<String, CallableStatement> callableStatementCache = null;
/** Session */
private Session session = null;
/**
* Constructor
*
* #param entityManager Entity manager
*/
public ProcDao(EntityManager entityManager) {
super(entityManager);
}
/**
* Creates a callable statement and stores it in the callable statement cache.
*
* #param sqlString SQL statement
* #return Native query
* #throws SQLException Database error
*/
#SuppressWarnings({"deprecation"})
protected CallableStatement prepareCall(String sqlString) throws SQLException {
if (callableStatementCache == null) {
callableStatementCache = new HashMap<String, CallableStatement>();
}
CallableStatement callableStatement = callableStatementCache.get(sqlString);
if (callableStatement == null) {
if (session == null) {
session = (Session) entityManager.getDelegate();
}
SessionImplementor sessionImplementor = (SessionImplementor)session;
Connection conn = sessionImplementor.connection();
callableStatement = conn.prepareCall(sqlString);
callableStatementCache.put(sqlString, callableStatement);
}
return callableStatement;
}
/** Closes the cached callable statements and connections. */
public void close() {
if (callableStatementCache != null && callableStatementCache.size() > 0) {
for (CallableStatement callableStatement : callableStatementCache.values()) {
try {
Connection connection = callableStatement.getConnection();
callableStatement.close();
connection.close();
} catch (Throwable ex) {
ex.printStackTrace();
}
}
callableStatementCache.clear();
}
if (session != null) {
if(session.isOpen()){
session.disconnect();
}
session = null;
}
}
}
import java.sql.CallableStatement;
import java.sql.SQLException;
import javax.persistence.EntityManager;
public class ImportPriceLevelProcedureManagerDao extends ProcDao {
/**
* Constructor
*
* #param entityManager {#link EntityManager}
*/
public ImportPriceLevelProcedureManagerDao(EntityManager entityManager) {
super(entityManager);
}
public void invokeImportPriceFromTempTableProcedure(int sessionId, String userID) throws DataException {
CallableStatement cStmt = null;
try {
cStmt = prepareCall("{call CPRPA_TPT_PRICE_CALC.tpt_data_import(?,?)}");
cStmt.setInt(1, sessionId);
cStmt.setString(2, userID);
cStmt.execute();
} catch (SQLException e) {
throw new DatabaseException("Database exception occured!" + e);
} catch (RuntimeException e) {
throwDataException(e);
} finally {
try {
cStmt.close();
} catch (SQLException e) {
throw new DatabaseException("Unable to release the Callable Statement");
}
}
}
#Stateful(name = "xxxx/ImportPriceLevelProcedureManager")
public class ImportPriceLevelProcedureManagerBean extends ProcManagerBean<ImportPriceLevelProcedureManagerDao> implements ImportPriceLevelProcedureManager, ImportPriceLevelProcedureManagerLocal {
/** Entity-Manager */
#PersistenceContext(type = PersistenceContextType.TRANSACTION, unitName = "xxxx")
private EntityManager entityManager;
/**
* Set entity manager for testing purpose
*
* #param entityManager {#link EntityManager}
*/
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
/** {#inheritDoc} */
#Override
public void invokeImportPriceFromTempTableProcedure(int sessionId, String userID) throws DataException {
getDao().invokeImportPriceFromTempTableProcedure(sessionId, userID);
}

Related

Is it possible to reuse a connection statement without closing it? [duplicate]

I've been working at this for almost a day and a half now and I can't seem to work this error out. I don't know why the ResultSet is being closed. Maybe some of you can help me out.
MySQLDatabase:
package net.gielinor.network.sql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public abstract class MySQLDatabase {
private String host;
private String database;
private String username;
private String password;
private Connection connection = null;
private Statement statement;
public MySQLDatabase(String host, String database, String username, String password) {
this.host = host;
this.database = database;
this.username = username;
this.password = password;
}
public abstract void cycle() throws SQLException;
public abstract void ping();
public void connect() {
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(String.format("jdbc:mysql://%s/%s", host, database), username, password);
statement = connection.createStatement();
} catch (Exception e) {
e.printStackTrace();
}
}
public void ping(String table, String variable) {
try {
statement.executeQuery(String.format("SELECT * FROM `%s` WHERE `%s` = 'null'", table, variable));
} catch (Exception e) {
connect();
}
}
public ResultSet query(String query) throws SQLException {
if (query.toLowerCase().startsWith("select")) {
return statement.executeQuery(query);
} else {
statement.executeUpdate(query);
}
return null;
}
public Connection getConnection() {
return connection;
}
}
MySQLHandler
package net.gielinor.network.sql;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import net.gielinor.network.sql.impl.MySQLDonation;
public class MySQLHandler extends Thread {
private static final MySQLHandler mysqlHandler = new MySQLHandler();
public static MySQLHandler getMySQLHandler() {
return mysqlHandler;
}
private static List<MySQLDatabase> updateList;
private static String host;
private static String database;
private static String username;
private static String password;
#Override
public void run() {
while (true) {
for (MySQLDatabase database : updateList) {
try {
if (database.getConnection() == null) {
database.connect();
} else {
database.ping();
}
database.cycle();
} catch (Exception ex) {
ex.printStackTrace();
}
try {
Thread.sleep(10000);
} catch (Exception ex) {
}
}
}
}
private static void loadProperties() {
Properties p = new Properties();
try {
p.load(new FileInputStream("./sql.ini"));
host = p.getProperty("host");
database = p.getProperty("database");
username = p.getProperty("username");
password = p.getProperty("password");
} catch (Exception ex) {
System.out.println("Error loading MySQL properties.");
}
}
public static String getHost() {
return host;
}
static {
loadProperties();
updateList = new ArrayList<MySQLDatabase>();
updateList.add(new MySQLDonation(host, database, username, password));
}
}
MySQLDonation
package net.gielinor.network.sql.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import net.gielinor.game.model.player.Client;
import net.gielinor.game.model.player.PlayerHandler;
import net.gielinor.game.model.player.PlayerSave;
import net.gielinor.network.sql.MySQLDatabase;
public final class MySQLDonation extends MySQLDatabase {
public MySQLDonation(String host, String database, String username, String password) {
super(host, database, username, password);
}
#Override
public void cycle() throws SQLException {
ResultSet results = query("SELECT * FROM `gieli436_purchases`.`donations`");
if (results == null) {
return;
}
while (results.next()) {
String username = results.getString("username").replace("_", " ");
System.out.println("name=" + username);
Client client = (Client) PlayerHandler.getPlayer(username.toLowerCase());
System.out.println(client == null);
if (client != null && !client.disconnected) {
int creditamount = results.getInt("creditamount");
if (creditamount <= 0) {
continue;
}
handleDonation(client, creditamount);
query(String.format("DELETE FROM `gieli436_purchases`.`donations` WHERE `donations`.`username`='%s' LIMIT 1", client.playerName.replaceAll(" ", "_")));
}
}
}
#Override
public void ping() {
super.ping("donations", "username");
}
private void handleDonation(Client client, int creditamount) throws SQLException {
client.credits = (client.credits + creditamount);
client.sendMessage("Thank you for your purchase. You have received " + creditamount + " store credits.");
PlayerSave.save(client);
}
}
The exception occurs here: in the while loop within MySQLDonation and the actual stacktrace is this:
java.sql.SQLException: Operation not allowed after ResultSet closed
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:794)
at com.mysql.jdbc.ResultSetImpl.next(ResultSetImpl.java:7077)
at net.gielinor.network.sql.impl.MySQLDonation.cycle(Unknown Source)
at net.gielinor.network.sql.MySQLHandler.run(Unknown Source)
With this information let me say that this does work, I get my message and what not in-game but it repeats, like the user is never removed from the query so it gives them infinite rewards. If you need any more information feel free to ask.
When you run the Delete query, you use the same Statement that was used in the Select query. When you re-execute on the same Statement, the previous ResultSet gets closed.
To avoid this, you should create a new Statement everytime you execute a query. So remove statement = connection.createStatement(); from the connect() method in MySQLDatabase class, and replace all statement in that class to connection.createStatement(). You may also choose to delete the private variable statement altogether.
You can read more about it here.
this error is some time occur when we use same statement object for diff. types
check Statement objectsss;

com.mysql.jdbc.exception.jdbc4.MySQLNonTransientConnectionException: No operation allowed after connection closed

how to solve this problem and what is wrong in this code?
i know that the question has been asked before but i cant solve the problem
private void cb_categoriesPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
cb_categories.removeAllItems();
try {
String sql_c = "SELECT * FROM inventory.categories";
cc.pst = cc.c.prepareStatement(sql_c);
cc.rs = cc.pst.executeQuery();
while (cc.rs.next()) {
String c_name = cc.rs.getString("CategoryName");
cb_categories.addItem(c_name);
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
} finally {
try {
cc.rs.close();
cc.pst.close();
} catch (Exception e) {
}
}
}
Your ResultSet and PreparedStatement are not declared in method scope, so I have to assume that you've declared them elsewhere.
That's a big mistake.
You should declare the Statement and ResultSet in method scope.
You make an attempt to close your resources, but you should wrap them in individual try/catch blocks. You cannot risk one being closed and not the other.
There are other things I'd criticize about your code (e.g. SELECT *, mingling UI and database code together in a single class), but that's enough to start.
Start with an interface:
package persistence;
import java.util.List;
/**
* Created by Michael
* Creation date 8/20/2017.
* #link https://stackoverflow.com/questions/45787151/com-mysql-jdbc-exception-jdbc4-mysqlnontransientconnectionexception-no-operatio/45787321?noredirect=1#comment78532554_45787321
*/
public interface CategoryDao {
List<String> findAllCategories();
}
Then write a concrete implementation:
package database;
import database.util.DatabaseUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.sql.DataSource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Michael
* Creation date 8/20/2017.
* #link https://stackoverflow.com/questions/45787151/com-mysql-jdbc-exception-jdbc4-mysqlnontransientconnectionexception-no-operatio/45787321?noredirect=1#comment78532554_45787321
*/
public class CategoryDaoImpl implements CategoryDao {
private static final Log LOGGER = LogFactory.getLog(CategoryDaoImpl.class);
private static String SELECT_CATEGORIES = "SELECT CategoryName from inventory.Categories ";
private DataSource dataSource;
public CategoryDaoImpl(DataSource dataSource) {
this.dataSource = dataSource;
}
#Override
public List<String> findAllCategories() {
List<String> categories = new ArrayList<>();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = this.dataSource.getConnection().prepareStatement(SELECT_CATEGORIES);
rs = ps.executeQuery();
while (rs.next()) {
categories.add(rs.getString("CategoryName"));
}
} catch (SQLException e) {
LOGGER.error(String.format("Exception caught while selecting all category names"), e);
} finally {
DatabaseUtils.close(rs);
DatabaseUtils.close(ps);
}
return categories;
}
}
This is something that you can test with JUnit off to the side. Get it running perfectly, then give a reference to your UI code. It'll keep the UI and database code separate. You can use this DAO in any application without worrying about Swing or web UI.

How to insert values in database using function in java servlet and jsp

I am trying to add, update and delete using function but value is not inserted.
please help me for this. the value does not insert into database it gives error
in database values is not insert after saving the records
i have tried following code
package main;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
*
* #author abc
*/
public class TenantOperation {
private Connection conn;
public TenantOperation()
{
conn = ConnectionDb.getConnection();
}
public void addTenant(TenantClass tenantclass) {
try {
String sql = "INSERT INTO tenantmaster(flatno,ownername,contactno,flattype,buildingname) VALUES (?, ?, ?, ?, ?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, tenantclass.getFlatno());
ps.setString(2, tenantclass.getOwnername());
ps.setString(3, tenantclass.getMob());
ps.setString(4, tenantclass.getFlattype());
ps.setString(5, tenantclass.getBuildingname());
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void removeTenant(int tenantId) {
try {
String sql = "DELETE FROM tenantmaster WHERE tenantid=?";
PreparedStatement ps = conn
.prepareStatement(sql);
ps.setInt(1, tenantId);
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
Here I have accessed that addtenant(). i have connect that function in this class
package main;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* #author abc
*/
public class TenantHandler extends HttpServlet {
private static String insert= "/tenantadd.jsp";
private static String Edit = "/tenantadd.jsp";
private static String TenantRecords = "/tenantadd.jsp";
private TenantOperation tenantOperation;
public TenantHandler()
{
super();
tenantOperation = new TenantOperation();
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String redirect="";
String flatno = request.getParameter("flatno");
String action = request.getParameter("action");
if(action.equalsIgnoreCase("insert"))
{
int no = Integer.parseInt(flatno);
TenantClass tenantclass = new TenantClass();
tenantclass.setFlatno(no);
tenantclass.setOwnername(request.getParameter("ownername"));
tenantclass.setMob(request.getParameter("mob"));
tenantclass.setFlattype(request.getParameter("flattype"));
tenantclass.setBuildingname(request.getParameter("buildingname"));
tenantOperation.addTenant(tenantclass);
redirect = TenantRecords;
// request.setAttribute("tenantList", tenantOperation.getAllTenants());
//System.out.println("Record Added Successfully");
}
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
#Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}

Data Access object method not working

I am a student learning JSP, and I seem to have this issue in executing a method via an object of a DAO class. When the database connectivity and SQL query is given on the servlet itself it, it will work. But when given in the DAO class and a object is used, it doesn't work. Please help.
import dataaccessobjects.cartDAO1;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class addtoCartServ extends HttpServlet {
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
cartDAO1 newcart = new cartDAO1();
PrintWriter out = response.getWriter();
if (request.getParameter("submit") != null){
//out.println("added to cart");
try {
//out.println("submit not null");
String Uname = (String) request.getSession().getAttribute("Welcome");
String ino = request.getParameter("ino");
String iqnty = request.getParameter("quantity");
String iname = request.getParameter("iname");
if(newcart.addToCart(iname,Uname,ino,iqnty)){
out.println("added to cart");
}
} catch (SQLException ex) {
Logger.getLogger(addtoCartServ.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(addtoCartServ.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
The DAO class
public cartDAO1(){
}
public boolean addToCart(String iname,String username, String ino,String iqnty) throws SQLException, ClassNotFoundException{
boolean flag = false;
Class.forName("org.apache.derby.jdbc.ClientDriver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/styleomega","root","");
PreparedStatement ps = conn.prepareStatement("INSERT INTO cart(iname,uname,ino,iqnty) VALUES (?,?,?,?)");
// set the values for parameters
ps.setString(1,iname);
ps.setString(2,username);
ps.setString(3,ino);
ps.setString(4,iqnty);
int rs = ps.executeUpdate();
if (rs==1){
flag = true;
}
return flag;
}
}
You should be import the DAO class package in servlet then access it it will work like
import DAO.cartDao;
If you will not import then how to acces it
I don't understand exactly what is not working? But I have noticed, you're not closing statement and the database connection in your DAO class.
FYI: An example
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = // Retrieve connection
stmt = conn.prepareStatement(// Some SQL);
rs = stmt.executeQuery();
} catch(Exception e) {
// Error Handling
} finally {
try { if (rs != null) rs.close(); } catch (Exception e) {};
try { if (stmt != null) stmt.close(); } catch (Exception e) {};
try { if (conn != null) conn.close(); } catch (Exception e) {};
}

Cannot get datasource in static Java method

I'm trying to access Oracle datasource from CDI bean.
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.faces.bean.ViewScoped;
import javax.inject.Named;
import javax.sql.DataSource;
#Named("ParentIDNameResolveController")
#ViewScoped
public class ParentIDNameResolve implements Serializable
{
// Call the Oracle JDBC Connection driver
#Resource(name = "jdbc/Oracle")
private static DataSource ds;
// Get the ID if the parent
public static int ParentId(int chieldId) throws SQLException
{
int ParentId = 0;
if (ds == null)
{
throw new SQLException("Can't get data source");
}
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs;
try
{
conn = ds.getConnection();
ps = conn.prepareStatement("SELECT COMPONENTID, FKCOMPONENTID, COMPONENTSTATSID from COMPONENT where COMPONENTID = ?");
ps.setLong(1, chieldId);
rs = ps.executeQuery();
while (rs.next())
{
ParentId = rs.getInt("FKCOMPONENTID");
}
}
finally
{
if (ps != null)
{
ps.close();
}
if (conn != null)
{
conn.close();
}
}
return ParentId;
}
// Get Parent Name
public static String ParentName(int ParentId) throws SQLException
{
String ParentName = null;
if (ds == null)
{
throw new SQLException("Can't get data source");
}
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs;
try
{
conn = ds.getConnection();
ps = conn.prepareStatement("SELECT COMPONENTSTATSID, NAME from COMPONENTSTATS where COMPONENTSTATSID = ?");
ps.setLong(1, ParentId);
rs = ps.executeQuery();
while (rs.next())
{
ParentName = rs.getString("NAME");
}
}
finally
{
if (ps != null)
{
ps.close();
}
if (conn != null)
{
conn.close();
}
}
return ParentName;
}
}
Unfortunately when I reference datasource from static Java method I get this error:
Can't get data source
I'm not sure is it possible to access datasource from static Java method. Is there a way to fix this problem?
It's not sure that your container will inject anything with adnotation #Resource to a static field or a static method. Try to rethink your class and maybe make it as #ApplicationScoped then you will also have only one instance per application.
Here are little changes to your class:
#Named("ParentIDNameResolveController")
#javax.enterprise.context.ApplicationScoped // not from javax.faces.bean
public class ParentIDNameResolve implements Serializable
{
// Call the Oracle JDBC Connection driver
#Resource(name = "jdbc/Oracle")
private DataSource dataSource;
/*
Add getter/setter for DataSource
*/
public DataSource getDataSource() {
return this.ds;
}
public void DataSource setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/* Change method signature to non static */
public int ParentId(int chieldId) throws SQLException
{
DataSource ds = getDataSource();
// your code here
return ParentId;
}
/* Change method signature to non static */
public String ParentName(int ParentId) throws SQLException
{
DataSource ds = getDataSource();
// your code here
return ParentName;
}
}
Next you can use it in your code also as injected object and You can be sure that DataSource wont' be null but if it will be - check is it properly defined as DataSource in configuration files.

Categories