Related
How do I retry to connect to my database if the connection does not work for the first time?
I am using jdbi3 for my database connection
public static void main(String[] args) throws Exception {
startApp(args);
}
private static void startApp(String[] args) throws Exception {
try {
new Application().run(args);
} catch(SQLException ex) {
System.out.println("Could not connect to database.");
System.out.println("Try reconnecting...");
TimeUnit.SECONDS.sleep(2);
startApp(args);
}
}
I implemented this since new Application().run(args) is throwing the SQLException if there was no connection but the exception never got caught.
This will eventually cause a stack overflow. Better:
while (true) {
try (
new Application().run(args);
return;
} catch (SQLException e) {
continue;
}
}
But that's not all: This will retry on any SQL exception. So, if, say, the db is up but the first thing the app does is, say, create a table, but that table already exists, this will just end up re-trying and failing, forever, at a 2 second interval, and that's quite yucky. I suggest checking which -actual- SQLException is thrown if the DB is down (presumably, that's why you want to retry: Wait for the DB to return) and catching ONLY that one. Note ethat SQLException has more methods than most exception types do, such as .getSQLState(), which you should check to figure out if the error is in fact 'cannot connect to DB engine', vs some other problem.
Furthermore, it is likely that Application's run() method is catching all exceptions, and will log them, which means your attempt to catch them isn't going to do anything. In this case, you'd have to edit the code of run().
I have a ITestListener to note test results. In my locator class if I try to handle something in catch statement, none of the code inside the catch is executed. For ex : I am trying to handle a WebElement that may or may not throw exception. When it throws exceptions, I should handle in the catch statement and locate different element. Since catch statement is not being executed and when the exception occurs, the applications just halts. Is there a way I could run the catch statement even when onTestFailure method is ON from TestNG ? Please suggest a solution.
//Test Script
public boolean loginVerification(String username, String password) {
try {
utilities.click(helloSignInLink, "elementToBeClickable");
reportLog("debug","info","Clicked on SignIn link");
utilities.sendText(loginID, username);
reportLog("debug","info","Username entered");
utilities.sendText(passwordID, password);
reportLog("debug","info","Password entered");
utilities.click(submit, "elementToBeClickable");
reportLog("debug","info","Clicked on submit button");
Thread.sleep(2000);
isTrue = driver.getTitle().contains("Vectors");
}
catch(Exception e) {
reportLog("debug","info","Unable to login with username : "+username+" , error message : "+e);
isTrue = false;
}
return isTrue;
}
I would recommend to catch Throwable - not just an Exception. Another thing is that when you catch something the excepttion does not really go up the stack so TestNG would never know if anything went wrong in your test and test listener would not detect failure. There is the way to push the exception further on after you have cought it. Like:
catch(Throwable e) {
reportLog("debug","info","Unable to login with username : "+username+" , error message : "+e);
isTrue = false;
throw e;
}
Can you correct your approach and let us know if the issue still exists?
P.S. - I also cannot see any assertions in your code. Assert results or Exception define the test result.
That means you are not catching the same error catch block.
Either use the same exception like TimeoutException so this block will only if TimeoutException occur. If you not sure about the error use generic exception block like Exception it will for sure going to execute if any error occur. In this case Exception will not execute for TimeoutException only because you have already specify same
try {
System.out.println("Your code");
}catch(TimeoutException t) {
System.out.println(t.getMessage());
}catch(Exception ex) {
ex.getStackTrace();
}
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.
Can someone explain the difference between catching an Exception and catching an SQLException? I know that SQLException will print out more information if you choose to print out the exception errors, but is there anything else?
try {
//code
} catch(Exception ex) {
//code
}
And
try {
//code
} catch(SQLException ex) {
//code
}
What are the benefits and differences of using Exception and SQLException in the catch block?
This is not the only difference.
Catching Exception is dangerous because it also catches all RuntimeExceptions (therefore unchecked exceptions), and that include niceties such as NullPointerException etc which are clear programmer errors. Don't do that!
Also, Exception is a class like any other, so you can subclass it and add constructors/methods of yours. For instance, SQLException has a .getErrorCode() method which Exception does not have. If you only catch Exception, you cannot access this method.
In general, catching the "more precise" exception first is the best. For instance, with the new (in Java 7...) file API, you can easily distinguish between filesystem level errors and other I/O errors, since FileSystemException extends IOException:
try {
something();
} catch (FileSystemException e) {
// fs level error
} catch (IOException e) {
// I/O error
}
It's all about the hierarchy,when you are talking about the catching the exception.
Technically speaking, Exception - is the super class which catches each and every exception.
If you are writing something related to SQL in the try block and you know it may even throw SQL Exception.
Then you may declare it this way as well.
try
{
}catch(SQLException ex)
{
Do this,when SQL Exception is caught.
}
catch(Exception ex)
{
Generic Exception - works for all
}
SQLException inherits from Exception, so SQLException will contain more (and more specific) information than Exception (which is intended to apply generally to all exceptions).
You can also have multiple catch clauses; so you can first try to catch the SQLException, but if it's not a SQLException, then you can just catch the general Exception.
In general, you shouldn't catch exceptions unless you intend to handle them in some way. You can have a top-level exception handler that catches any exceptions that bubble up to the top of the call stack, so that your program doesn't crash on unhandled exceptions.
A - Explanation
SQLException is a subtype of java.lang.Exception and also it is implementing the Iterable<Throwable> class. Programmers prefer throwing different subtypes of Exception class because on some higher level, they want to catch the exact sub-Exception class so that they can be sure that that specific Exception is thrown on some exact scenario. Thus, they can know the exact source of Exception.
B - Example
Consider you have written a method that throws multiple exceptions. Let's say, you take a json String and parse it, then persist it on the database. Consider the following method;
public boolean persistCustomer(String jsonString) throws SQLException, IOException {
Connection conn = getConnection();
PreparedStatement preparedStatement = null;
ObjectMapper objectMapper = new ObjectMapper();
try {
Customer customer = objectMapper.readValue(jsonString, Customer.class);
preparedStatement = conn.prepareStatement(PERSIST_CUSTOMER);
preparedStatement.setString (1, customer.getName());
preparedStatement.setInt (2, customer.getAge());
preparedStatement.setBoolean (3, customer.getIsRegular());
preparedStatement.executeUpdate();
return true;
} catch (IOException e) {
throw e;
} finally {
try {
if (preparedStatement != null)
preparedStatement.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
In this method, we are converting JSON into a Customer class and also we persist customer class to the database.
The following lines throw SQLException;
preparedStatement = conn.prepareStatement(PERSIST_CUSTOMER);
preparedStatement.setString (1, customer.getName());
preparedStatement.setInt (2, customer.getAge());
preparedStatement.setBoolean (3, customer.getIsRegular());
preparedStatement.executeUpdate();
prepareStatement(), setters and executeUpdate() methods, all of them throwing SQLException's. But also, the line that which we convert JSON in a String into a Customer object, also throws several Exceptions other than SQLException.
Customer customer = objectMapper.readValue(jsonString, Customer.class);
readValue() method throws JsonParseException, JsonMappingException and also IOException. All of them can be catched using an IOException because the JSON related exceptions extend IOException.
I'm going to provide two different examples so that it will be obvious to understand why we need different types of Exceptions.
C - Bad Practice: Using Exception To Catch All Exceptions
public class BadPracticeExample {
public static void main(String[] args) {
MySQLUtil dbUtil = new MySQLUtil();
String jsonString = "{\"name\":\"Levent\",\"age\":31,\"isRegular\":true}";
try {
dbUtil.persistCustomer(jsonString);
} catch (Exception e) {
System.out.println("A problem occured");
}
}
}
As you can see, it catches the Exception but what are we going to do if we need special exception handling for two different sources of problems? persistCustomer can throw either IOException or an SQLException and what if we need to do different set of tasks to handle those problems? I want to send an email to the database admin when an SQLException occurs and I want to continue when a JSON parsing problem occurs, on the case that an IOException is catched?
In this scenario you can't do that. Here is the output of the code snippet above and we are only sure that an Exception occured but we don't have any idea about what is the source of it;
A problem occured
D - Good Practice Example I: SQL Exception catched
public class GoodPracticeExample {
public static void main(String[] args) {
MySQLUtil dbUtil = new MySQLUtil();
String jsonString = "{\"name\":\"Levent\",\"age\":31,\"isRegular\":true}";
try {
dbUtil.persistCustomer(jsonString);
} catch (SQLException e) {
System.out.println("SQL Exception catched, SQL State : " + e.getSQLState());
System.out.println("Error Code : " + e.getErrorCode());
System.out.println("Error Message : " + e.getMessage());
} catch (IOException e) {
System.out.println("Cannot parse JSON : " + jsonString);
System.out.println("Error Message : " + e.getMessage());
}
}
}
As you can see, we catch for both, JSON and SQL problem and in this example, submethod is trying to persist DB where there is no table. The output is as below;
SQL Exception catched, SQL State : 42000
Error Code : 1142
Error Message : INSERT command denied to user 'levent'#'example.com' for table 'CUSTOMER'
So we have catched SQL Exception and we have all parameters we need to send an alarm email. We can add additional handler or utility methods on the SQLException catch block.
D - Good Practice Example II: IOExceptoin catched on Parsing Error
public class GoodPracticeExample {
public static void main(String[] args) {
MySQLUtil dbUtil = new MySQLUtil();
String jsonString = "{\"Zname\":\"Levent\",\"age\":31,\"isRegular\":true}";
try {
dbUtil.persistCustomer(jsonString);
} catch (SQLException e) {
System.out.println("SQL Exception catched, SQL State : " + e.getSQLState());
System.out.println("Error Code : " + e.getErrorCode());
System.out.println("Error Message : " + e.getMessage());
} catch (IOException e) {
System.out.println("Cannot parse JSON : " + jsonString);
System.out.println("Error Message : " + e.getMessage());
}
}
}
If you've noticed, I"ve corrupted the JSON to cause an IOException. Now in the json string, instead of "name", "Zname" is written which will cause Jackson Parser to fail. Let's checkout the output of this code.
Cannot parse JSON : {"Zname":"Levent","age":31,"isRegular":true}
Error Message : Unrecognized field "Zname" (class com.divilioglu.db.utils$Customer), not marked as ignorable (3 known properties: "isRegular", "name", "age"])
at [Source: (String)"{"Zname":"Levent","age":31,"isRegular":true}"; line: 1, column: 11] (through reference chain: com.divilioglu.db.utils.MySQLUtil$Customer["Zname"])
As you can see, we catched the specific scenario and we are sure, this comes from the line in dbUtil.persistCustomer() method which can be seen below;
Customer customer = objectMapper.readValue(jsonString, Customer.class);
E - Conclusion
So as it is a best practice to create new Exceptions by extending existing Exception classes. While writing your code at first, you may think that it is an overkill and you won't need additional Exception classes, but you will need them when you need distinguish the source of the problem and handle them independently.
In this example demonstrated above, I can independently catch IOException and SQLException and the sources of both Exceptions are coming from the same method. I want to distinguish both so that I can handle them independently. You cannot have that flexibility if you just wrap all the Exceptions with the base Exception class.
Exception is a standard class from which every exceptions inherit.
SQLException is a class that inherits from Exception and that is designed specifically for database(SQL) exceptions.
By doing
try {
// Your code here
} catch (Exception e) {
// Catching here
}
You are catching every type of exception possible... But then, you might not be able to know how to react to a specific exception.
but by doing
try {
// Your code here
} catch (SQLException e) {
// Catching here
}
You know that the exception happened while working on a database and it helps you know how to react to the exception.
As you see SQLException extends exception. So that's the only difference really. When you are catching exception then you will catch ALL exceptions (which is bad). But when you are catching SQLException then you catch only that(which is good because that is what you are seeking).
If an exception in between the try and catch blocks is thrown that is not a SQL Exception (these will typically only come from database-related code), for example a Null Pointer Exception, the Exception catch will catch it but the SQLException will not.
SQLException is an Exception so you are just getting a more specific exception.
According to Oracle's javadocs, this specific information you get is:
a string describing the error. This is used as the Java Exception
message, available via the method getMessage.
a "SQLstate" string, which follows either the XOPEN SQLstate
conventions or the SQL:2003 conventions. The values of the SQLState
string are described in the appropriate spec. The DatabaseMetaData
method getSQLStateType can be used to discover whether the driver
returns the XOPEN type or the SQL:2003 type.
an integer error code that is specific to each vendor. Normally this
will be the actual error code returned by the underlying database.
a chain to a next Exception. This can be used to provide additional
error information.
the causal relationship, if any for this SQLException.
SQLException is a specialized exception derived from Exception.
If you catch Exception, all exception shall get caught. Even undesirable exceptions.
If you catch only its specialiazation, the SQLException, only the SQLException itself or its derived shall get caught.
One shall catch only exceptions one can handle or wishes to handle, and let the others bubble up.
For further reference, please take a look at the following:
Exception
SQLException
SQL exception is a frequent error while working in Java Database Connectivity (JDBC).Its related to accessing or setting column in your SQL Query using prepared statement.
SQLException is a derived from Exception and contains more specific information related to accessing or setting column in your SQL query, while exception is usually more general.
hey all, I'm new to Java and was wondering if I define a method to return a database object
like
import java.sql.*;
public class DbConn {
public Connection getConn() {
Connection conn;
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
if(System.getenv("MY_ENVIRONMENT") == "development") {
String hostname = "localhost";
String username = "root";
String password = "root";
}
conn = DriverManager.getConnection("jdbc:mysql:///mydb", username, password);
return conn;
} catch(Exception e) {
throw new Exception(e.getMessage());
}
}
}
if the connection fails when I try to create it what should I return? eclipse is telling me I have to return a Connection object but if it fails I'm not sure what to do.
thanks!
UPDATED CODE TO LET EXCEPTION BUBBLE:
public class DbConn {
public Connection getConn() throws SQLException {
Connection conn;
String hostname = "localhost";
String username = "root";
String password = "root";
Class.forName("com.mysql.jdbc.Driver").newInstance();
if(System.getenv("MY_ENVIRONMENT") != "development") {
hostname = "localhost";
username = "produser";
password = "prodpass";
}
conn = DriverManager.getConnection("jdbc:mysql:///mydb", username, password);
return conn;
}
}
If an exception is thrown, there is no normal value returned from the method. Usually the compiler is able to detect this, so it does not even pester you with "return required" style warnings/errors. Sometimes, when it is not able to do so, you need to give an "alibi" return statement, which will in fact never get executed.
Redefining your method like this
public Connection getConn() {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
if(System.getenv("MY_ENVIRONMENT") == "development") {
String hostname = "localhost";
String username = "root";
String password = "root";
}
conn = DriverManager.getConnection("jdbc:mysql:///mydb", username, password);
} catch(Exception e) {
// handle the exception in a meaningful way - do not just rethrow it!
}
return conn;
}
will satisfy Eclipse :-)
Update: As others have pointed out, re-throwing an exception in a catch block the way you did is not a good idea. The only situation when it is a decent solution is if you need to convert between different exception types. E.g. a method called throws an exception type which you can not or do not want to propagate upwards (e.g. because it belongs to a proprietary library or framework and you want to isolate the rest of your code from it).
Even then, the proper way to rethrow an exception is to pass the original exception into the new one's constructor (standard Java exceptions and most framework specific exceptions allow this). This way the stack trace and any other information within the original exception is retained. It is also a good idea to log the error before rethrowing. E.g.
public void doSomething() throws MyException {
try {
// code which may throw HibernateException
} catch (HibernateException e) {
logger.log("Caught HibernateException", e);
throw new MyException("Caught HibernateException", e);
}
}
You should just eliminate your entire try/catch block and allow exceptions to propagate, with an appropriate exception declaration. This will eliminate the error that Eclipse is reporting, plus right now your code is doing something very bad: by catching and re-throwing all exceptions, you're destroying the original stack trace and hiding other information contained in the original exception object.
Plus, what is the purpose of the line Class.forName("com.mysql.jdbc.Driver").newInstance();? You're creating a new mysql Driver object through reflection (why?) but you're not doing anything with it (why?).
Never, ever, ever use a generic exception like that. If you don't have a ready made exception (in this case, an SQLException), make your own exception type and throw it. Every time I encounter something that declares that it "throws Exception", and it turns out that it does so because something it calls declares "throws Exception", and so on down the line, I want to strangle the idiot who started that chain of declarations.
This is exactly the situation where you should let the exception propagate up the call stack (declaring the method as throws SQLException or wrapping it in a application-specific exception) so that you can catch and handle it at a higher level.
That's the whole point of exceptions: you can choose where to catch them.
I'm sorry, but you shouldn't be writing code like this, even if you're new to Java.
If you must write such a thing, I'd make it more like this:
public class DatabaseUtils
{
public static Connection getConnection(String driver, String url, String username, String password) throws SQLException
{
Class.forName(driver).newInstance();
return DriverManager.getConnection(url, username, password);
}
}
And you should also be aware that connection pools are the true way to go for anything other than a simple, single threaded application.
Try this one
public ActionForward Login(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
MigForm migForm = (MigForm) form;// TODO Auto-generated method stub
Connection con = null;
Statement st = null;
ResultSet rs = null;
String uname=migForm.getUname();
String pwd=migForm.getPwd();
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:XE","uname","pwd");
if(con.isClosed())
{
return mapping.findForward("success");
}
//st=con.createStatement();
}catch(Exception err){
System.out.println(err.getMessage());
}
return mapping.findForward("failure");
}