I have a method that call a procedure, see:
public void myMethod() {
((Session) em.getDelegate()).doWork(new Work() {
#Override
public void execute(Connection connection) throws SQLException {
StringBuilder sqlSP = new StringBuilder();
sqlSP.append("{ call myprocedure ");
sqlSP.append("(?) }");
CallableStatement cs = connection.prepareCall(sqlSP.toString());
cs.setInt(1, 1);
try {
cs.execute();
} finally {
if (!cs.isClosed()) {
cs.close();
}
}
}
});
}
This works very well in tomcat, because method isClosed() exists. But when i upload my application to jboss 5.1 i got following error:
Caused by: java.lang.AbstractMethodError: net.sourceforge.jtds.jdbc.JtdsCallableStatement.isClosed()Z
at org.jboss.resource.adapter.jdbc.jdk6.WrappedCallableStatementJDK6.isClosed(WrappedCallableStatementJDK6.java:64)
My tomcat and jboss, both use jTDS 1.2.5, so i can't understand what is the problem. I tried to debug jboss with WrappedCallableStatement but when i try to inspect line "cs.isClosed" i got nestedException.
Related
I have piece of code which is working fine with oracle db but giving exception SQL state [HY000]; error code [1205]; (conn=30) Lock wait timeout exceeded; try restarting transaction; nested exception is java.sql.BatchUpdateException: (conn=30) Lock wait timeout exceeded; try restarting transaction when trying to execute with mariadb . I have tried multiple solutions i.e. increased innodb_lock_wait_timeout , changed the ##GLOBAL.tx_isolation, ##tx_isolation but still getting the same error . Here is the code which is working fine with orcale but giving exception with mariadb:
public void updateFailureData(final Long mId, final Set<String> errorVals) {
try {
this.jdbcTemplate.batchUpdate("UPDATE MARKETS SET ERR_VALS = ? WHERE M_ID = ?", new BatchPreparedStatementSetter() {
#Override
public void setValues(final PreparedStatement preparedStatement, final int arg1) throws SQLException {
int index = 1;
preparedStatement.setString(index++, StringUtils.join(errorVals, ","));
preparedStatement.setLong(index, mId);
}
#Override
public int getBatchSize() {
return 1;
}
});
} catch (DataAccessException dataAccessException) {
System.out.println("Updating errorVals.", dataAccessException);
}
}
Is there anything which can be done or I am missing ?
An Azure Function that I am building needs to be able to execute a procedure in an Azure SQL Server Database.
I have working Java code in Eclipse (based on #duffmo's answer in Java DB connection)
I then ported the code to an Azure Function in Visual Studio Code, for deployment to Azure. (Note I have removed security code etc.) I created the project using View/Command Palette/Azure Functions - Create New Project
package com.function;
import java.sql.*;
import java.util.*;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
/**
* Azure Functions with HTTP Trigger.
*/
public class Function {
/**
* This function listens at endpoint "/api/HttpTrigger-Java". Two ways to invoke
* it using "curl" command in bash: 1. curl -d "HTTP Body" {your
* host}/api/HttpTrigger-Java&code={your function key} 2. curl "{your
* host}/api/HttpTrigger-Java?name=HTTP%20Query&code={your function key}"
* Function Key is not needed when running locally, it is used to invoke
* function deployed to Azure. More details:
* https://aka.ms/functions_authorization_keys
*/
private static final String DEFAULT_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static final String DEFAULT_URL = "jdbc:sqlserver://myserver.database.windows.net:1433;database=mydb;loginTimeout=10;user=myuser#myserver;password=mypassword;";
#FunctionName("HttpTrigger-Java")
public HttpResponseMessage run(#HttpTrigger(name = "req", methods = { HttpMethod.GET,
HttpMethod.POST }, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
Connection connection = null;
try {
connection = createConnection(DEFAULT_DRIVER, DEFAULT_URL,context);
connection.setAutoCommit(false);
String sqlUpdate = "{call MYDB.MYPROC(?,?}";
List<Object> parameters = Arrays.asList("Bar", "Foo");
execute(connection, sqlUpdate, parameters);
connection.commit();
} catch (Exception e) {
rollback(connection);
e.printStackTrace();
} finally {
close(connection);
}
return null;
}
public static Connection createConnection(String driver, String url, ExecutionContext context) throws ClassNotFoundException, SQLException {
Class.forName(driver);
return DriverManager.getConnection(url);
}
public static void close(Connection connection) {
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(Statement st) {
try {
if (st != null) {
st.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void rollback(Connection connection) {
try {
if (connection != null) {
connection.rollback();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static double execute(Connection connection, String sql, List<Object> parameters) throws SQLException {
CallableStatement call = connection.prepareCall(sql);
try {
int i = 0;
for (Object parameter : parameters) {
call.setObject(++i, parameter);
}
call.executeUpdate();
} finally {
close(call);
}
return 0;
}
}
However the line
Class.forName(driver);
causes the following error
java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at java.base/java.lang.Class.forName0(Native Method)
I tried to solve this by
Putting the sqljdbc4.jar in a "lib" directory
Manually adding the following to the pom.xml
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>sqljdbc4</artifactId>
<version>4.0</version>
</dependency>
Trying to install the jar from the terminal via
mvn install:install-file -Dfile=’C:=myPath\myFunction\lib\sqljdbc4.jar'
-DgroupId=package -DartifactId=sqljdbc4 -Dversion='4.0' -Dpackaging=jar
experimented with changing the order of 'microsoft' and 'sqlserver' in the DEFAULT_DRIVER string.
Try and add SQLJDBC from the new Java Dependencies view (see #hemangs answer) - but it does not appear in the list
I edited the .classPath as per #asndr's answer in .classpath - note that I did not manage to access the .classPath from within VS Code, but rather via File Explorer - and then ran view/Command Palette/Java: Clean the java language server workspace
Any ideas?
Based on #nirmal's answer in Missing artifact com.microsoft.sqlserver:sqljdbc4:jar:4.0
I did the following:
Explorer/Java Dependencies/Maven Dependencies - then clicked on '+'
Typed in mssql-jdbc and pressed Enter
Selected mssql-jdbc from com.microsoft.sqlserver
This opened the pom.xml within VS Code with the following added
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>8.3.0.jre14-preview</version>
</dependency>
I changed the version number to 6.1.0.jre8 (the higher version caused compile errors)
Saved
VS Code asked me if I want to 'A build file was modified. Do you want to synchronize the Java classpath/configuration?'
I said yes, and then it worked.
What seems to be crucial is to edit the pom.xml from within VS Code. It seems that when I edited it outside of VS Code, then VS Code did not trigger a synchronization of the configuration.
I am trying to use PowerMockito to mock by DBUtil. Unlike typical testcase, I don't want to mock the db calls completely. Whenever Dbutil.getConnection() is called. I want to return the connection object to my local Database.
The simple jdbc connection code below is not working when i call from #BeforeClass method. But it works when I call from the java class.
public static Connection getConnection() throws Exception {
System.out.println("-------- Connecting to " + Constants.CONNECTION_STR + " ------");
try {
Class.forName(Constants.ORACLE_DRIVER_NAME);
}
catch (ClassNotFoundException e) {
throw new Exception("JDBC Driver not found... " + e);
}
catch (Exception e) {
// TODO: handle exception
System.out.println("getConnection :: exp :: "+ e);
}
System.out.println("Oracle JDBC Driver Registered Sucessfully!");
Connection connection = null;
try {
connection = DriverManager.getConnection(Constants.CONNECTION_STR, Constants.USERNAME, Constants.PASSWORD);
}
catch (SQLException e) {
throw new Exception("Connection Failed!",e);
}
if (connection != null) {
System.out.println("Connected to Database Sucessfully, take control your database now!");
return connection;
}
System.out.println("Failed to make connection!");
return null;
}
My Testclass
#RunWith (PowerMockRunner.class)
#PrepareForTest(DbUtil.class)
public class MyUtilTest {
#Mock
private DbUtil dbUtil;
#InjectMocks
private MyUtil myUtil;
private static Connection myDBConn;
#BeforeClass
public static void beforeClass() throws Exception {
myDBConn = OracleJDBCConnetion.getConnection(); // This always throws invalid username/password exception.
}
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void testIsAdminUser() throws Throwable{
PowerMockito.mockStatic(DbUtil.class);
PowerMockito.when(DbUtil.getConnection()).thenReturn(myDBConn);
String accId= "TH123" ;
boolean isAdmin = MyUtil.isAdminUser(cloudAccGuid);
System.out.println("isAdmin : " + isAdmin);
//then
PowerMockito.verifyStatic(Mockito.times(1));
DbUtil.getConnection();
assertTrue(isAdmin);
//Finally I am closing my connection.
if(myDBConn!=null && !myDBConn.isClosed())
OracleJDBCConnetion.closeConnection(myDBConn);
}
}
The beforeClass method always throws below expection.
Connection Failed! java.sql.SQLException: ORA-01017: invalid username/password; logon denied
But the same code works, when i try from normal Java class.
Can anyone help in understanding whats wrong here?
I am using ojdbc6.jar and powermokito-1.5.6 and my Oracle database version is 11.2.0.4.0
Thanks.
Edit :
I found that #PrepareForTest annotation is causing the error. without the annotation connection is successful but mock does not work. can anyone help me in understanding what is happening? I am very new to these mocking stuff.
The problem with #PrepareForTest annotation is, it recursively creates stubs for all dependent classes. Since DBUtil class uses java.sql.Connection class , a stub is created for Connection class also.
So, When i try to create connection, it refers to stub class and throws expection.
Add #PowerMockIgnore annotation to the class,to avoid it. #PowerMockIgnore annotation tells the powermock not to create for the classes that falls under the given package.
#RunWith (PowerMockRunner.class)
#PrepareForTest({DbUtil.class})
#PowerMockIgnore({"java.sql.*"})
public class MyUtilTest {
...
}
This worked for me.
I've implement an application, it works when I code in Windows. But the same code gave Exception in Mac. I use SQLite database and have put sqlite-jdbc-3.21.0.1.jar as library.
I know the driver went ok since I have check it like below:
public static void pureSqlite() throws Exception {
String url = "jdbc:sqlite:hadits-bukhari.sqlite";
Connection connection = DriverManager.getConnection(url);
System.out.println("Connection established.");
String sql = "SELECT * FROM hadits";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
int i = 0;
while (resultSet.next()) {
if (i == 5) break;
System.out.println(resultSet.getInt("nomer")+". "+resultSet.getString("deskripsi"));
i++;
}
}
It works perfectly when I used my Windows computer.
Then, I've implement it with ORMLite's way. Create Hadits class with required annotation. Then I have below function:
public static void withOrmLite() throws Exception {
Class.forName("org.sqlite.JDBC"); // even put this test
System.out.println("Frankly, class org.sqlite.JDBC is exists.");
Ilmu ilmu = new IlmuImpl();
List<Hadits> list = ilmu.findHadits("bukhari", "");
int i = 0;
for (Hadits item: list) {
if (i == 10) break;
System.out.println(item.number+". "+item.desc);
i++;
}
}
From IlmuImpl:
#Override
public List<Hadits> findHadits(String book, String keyword) throws Exception {
String dbHost = "jdbc:sqlite:hadits-"+book+".sqlite";
ConnectionSource connection = new JdbcConnectionSource(dbHost);
Dao<Hadits, Long> haditsDao = DaoManager.createDao(connection, Hadits.class);
List<Hadits> list;
if (keyword == null || keyword.trim().length() == 0) {
list = haditsDao.queryForEq("buku", book);
} else {
QueryBuilder<Hadits, Long> queryBuilder = haditsDao.queryBuilder();
queryBuilder.where().like("deskripsi", "%"+keyword+"%");
PreparedQuery<Hadits> preparedQuery = queryBuilder.prepare();
list = haditsDao.query(preparedQuery);
}
connection.close();
return list;
}
This code do fine in Windows, but failed when I use the same code in Mac, says:
Exception in thread "main" java.sql.SQLException: Driver class was not found for SQLite database. Missing jar with class org.sqlite.JDBC.
at com.j256.ormlite.misc.SqlExceptionUtil.create(SqlExceptionUtil.java:27)
at com.j256.ormlite.db.BaseDatabaseType.loadDriver(BaseDatabaseType.java:47)
at com.j256.ormlite.jdbc.JdbcConnectionSource.initialize(JdbcConnectionSource.java:137)
at com.j256.ormlite.jdbc.JdbcConnectionSource.<init>(JdbcConnectionSource.java:117)
at com.j256.ormlite.jdbc.JdbcConnectionSource.<init>(JdbcConnectionSource.java:59)
at ilmu.implementation.IlmuImpl.findHadits(IlmuImpl.java:17) <-- this is my class
...
Caused by: java.lang.ClassNotFoundException: org.sqlite.JDBC
...
What could be wrong?
Caused by: java.lang.ClassNotFoundException: org.sqlite.JDBC
The exception is trying to tell you all that you need to know. Although you say that you "put sqlite-jdbc-3.21.0.1.jar as library", the JDBC class is not found. This means that there is something wrong with your classpath.
Either the library hasn't been added to the right directory or hasn't been properly identified as a dependency in your IDE, maven, or other build utility. If you give more details about your build environment, I can provide more specifics about tuning the dependencies.
I've integration solution based on weblogic application server. (Oracle Retail Integration Bus). Each adapter of solution is a EJB component.
Weblogic Console Application view
There are two types of Adapters, first one is for XA Transactions, and second one is for NONXA transactions. (NONXA needed when in PLSQL API function used External proc procedures).
XA - OracleObjectSubscriberComponentImpl
public class OracleObjectSubscriberComponentImpl
extends DefaultAdaptorComponentImpl
implements SubscriberComponent
{
....
protected void performSubscribe(RibContext ribContext, RibMessage inRibMessage, RibMessages outRibMsg)
throws RibAPIException
{
boolean success = false;
Connection connection = null;
try
{
setRibContext(ribContext);
setRibMessagesOut(outRibMsg);
connection = getNewConnection();
initCallableStatement(connection, null);
registerOutParams();
if (setInParams(inRibMessage))
{
execute();
processResult();
success = true;
}
}
finally
{
end(success);
cleanup();
super.closeConnection(connection);
}
}
public void performSubscribe(RibContext ribContext, RibMessage inRibMessage)
throws RibAPIException
{
performSubscribe(ribContext, inRibMessage, null);
}
public void subscribe(RibContext ribContext, RibMessage inRibMessage)
throws RibAPIException
{
performSubscribe(ribContext, inRibMessage);
}
...
}
NonXA - OracleObjectSubscriberComponentNonXAImpl extends OracleObjectSubscriberComponentImpl.
public class OracleObjectSubscriberComponentNonXAImpl
extends OracleObjectSubscriberComponentImpl
{
public void initCallableStatement(Connection c, String msgType)
throws RibAPIException
{
try
{
c.setAutoCommit(false);
}
catch (SQLException e)
{
this.LOG.error("Could not turn off AutoCommit", e);
throw createRibAPIException("initStmt", e);
}
super.initCallableStatement(c, msgType);
}
public void end(boolean successful)
{
super.end(successful);
try
{
if (successful) {
this.conn.commit();
} else {
this.conn.rollback();
}
this.conn.setAutoCommit(true);
}
catch (SQLException sqle)
{
String errorString = "Error occurred during commit/rollback";
this.LOG.error(errorString, sqle);
throw new RuntimeException(errorString, sqle);
}
}
public void subscribe(RibContext ribContext, RibMessage inRibMessage)
throws RibAPIException
{
NonTransactionalSubscriberCoreService nonTransactionalSubscriberCoreService = (NonTransactionalSubscriberCoreService)RetailServiceFactory.getService(NonTransactionalSubscriberCoreService.class);
nonTransactionalSubscriberCoreService.subscribe(this, ribContext, inRibMessage);
}
}
Differences between them is:
NonXA Autocommit = false, and this.conn.commit(); and this.conn.rollback(); used instead of XA Autocommit = true.
NonXA got overrided method subscribe, where new Proxy service created, and NonXA object goes into Proxy, where it will execute Perform Subscribe.
Non XA class uses NonTransactionalSubscriberCoreServiceEjb class, this is a Proxy service:
public class NonTransactionalSubscriberCoreServiceEjb
implements NonTransactionalSubscriberCoreService, SessionBean
{
...
public void subscribe(OracleObjectSubscriberComponentNonXAImpl subscriber, RibContext ribContext, RibMessage inRibMessage)
throws RibAPIException
{
RibContextFactory.setCurrentRibContext(ribContext);
subscriber.performSubscribe(ribContext, inRibMessage);
RibContextFactory.clearCurrentRibContext();
}
...
}
All Adapters does not parrallel, each adapter get messages one by one, from JMS Topic. XA component works fine, it get connection in weblogic datasource and return it back when work finished. NonXA does not working as expected, it take connection from datasourse and do not release it, connection hold up until timeout came.
If i change NonXA class, subscribe method to this:
public void subscribe(RibContext ribContext, RibMessage inRibMessage)
throws RibAPIException
{
this.performSubscribe(ribContext, inRibMessage);
}
Connections will be released after work finished, but i can't use External Proc in API, because ORA-xxx (this feature is not supported in XA) raised. I need keep NonXA functionality and release connections.
Solution:
If datasource managed from weblogic server.
From Weblogic console for the datasource,
uncheck "Keep Connection After Local Transaction"
check "Remove Infected Connections Enabled"
If datasource managed from appliaction, make same changes in datasource xml file.
<jdbc-data-source>
<name>rib-rms-managed-datasource</name>
<jdbc-driver-params>
<url>jdbc:oracle:thin:#monrmsdb.apm.local:1521:retekdb</url>
<driver-name>oracle.jdbc.xa.client.OracleXADataSource</driver-name>
<properties>
<property>
<name>user</name>
<value>RMS13DEV</value>
</property>
</properties>
</jdbc-driver-params>
<jdbc-connection-pool-params>
<initial-capacity>0</initial-capacity>
<max-capacity>350</max-capacity>
<capacity-increment>10</capacity-increment>
<connection-creation-retry-frequency-seconds>1</connection-creation-retry-frequency-seconds>
<test-connections-on-reserve>false</test-connections-on-reserve>
<profile-harvest-frequency-seconds>60000</profile-harvest-frequency-seconds>
<inactive-connection-timeout-seconds>5</inactive-connection-timeout-seconds>
<statement-cache-size>0</statement-cache-size>
<!-- Add this--><remove-infected-connections>true</remove-infected-connections>
<pinned-to-thread>false</pinned-to-thread>
</jdbc-connection-pool-params>
<jdbc-data-source-params>
<jndi-name>jdbc/OracleRibDs</jndi-name>
<global-transactions-protocol>TwoPhaseCommit</global-transactions-protocol>
<!-- Add this--><keep-conn-after-local-tx>false</keep-conn-after-local-tx>
</jdbc-data-source-params>
</jdbc-data-source>