changing webapp classpath loading order in junit

We have a legacy class that override the class from the jar file.

That override works well in webapp, but not in Junit. This is the Junit solution.

The load order of tomcat from ziggy

Bootstrap classes of your JVM
System class loader classes (described above)
/WEB-INF/classes of your web application
/WEB-INF/lib/*.jar of your web application
$CATALINA_HOME/common/classes
$CATALINA_HOME/common/endorsed/*.jar
$CATALINA_HOME/common/i18n/*.jar
$CATALINA_HOME/common/lib/*.jar
$CATALINA_BASE/shared/classes
$CATALINA_BASE/shared/lib/*.jar

Therefore, in Junit, we set the order of classpath correctly, and the problem gone.

รูปภาพ

java get table list and package arguments from oracle

static Connection conn;
 static Statement st;

public static void main(String args[]) throws Exception{
 DatabaseMetaData md = conn.getMetaData();
 ResultSet rs = md.getTables(null, null, "%", null);
 while (rs.next()) {
 System.out.println(rs.getString(3)); // list table name
 }

String procedureCat = "XXX0000"; // package name
 String procedureSchem = "USERNAMENAJA";
 String procedureName = "CALL";  // function

rs = md.getProcedureColumns(procedureCat, procedureSchem, procedureName, null);
  while (rs.next()) {
System.out.println("----");
System.out.println("column name: "+rs.getObject(4)); // column name
System.out.println("data type: "+new Integer(rs.getInt(6))); // data type
System.out.println("columnReturnTypeName "+rs.getString(7)); // column return type name
int dbColumnReturn = rs.getInt(5);
String procReturn = "";
System.out.println("column return type: "+dbColumnReturn); // column type
switch(dbColumnReturn)
{
case DatabaseMetaData.procedureColumnIn:
procReturn = "In";
break;
case DatabaseMetaData.procedureColumnOut:
procReturn = "Out";
break;
case DatabaseMetaData.procedureColumnInOut:
procReturn = "In/Out";
break;
case DatabaseMetaData.procedureColumnReturn:
procReturn = "return value";
break;
case DatabaseMetaData.procedureColumnResult:
procReturn = "return ResultSet";
default:
procReturn = "Unknown";
}
System.out.println("column return : " + procReturn);
}
 }

static {
 try {
 // Step 1: Load the JDBC driver.
 Class.forName("oracle.jdbc.driver.OracleDriver");
 System.out.println("Driver Loaded.");
 // Step 2: Establish the connection to the database.
 String url = "jdbc:oracle:thin:@192.168.XX.XX:1521:XE";

conn = DriverManager.getConnection(url, "username", "passwordnaja");
 System.out.println("Got Connection.");
<pre>st = conn.createStatement();
 } catch (Exception e) {
 System.err.println("Got an exception! ");
 e.printStackTrace();
 System.exit(0);
 }
 }

RESULT OF get function args

column name: null
data type: 1111
CLOB
column return type: 5
column return : return value
----
column name: IN_FUNC_NAME
data type: 12
VARCHAR2
column return type: 1
column return : In
----
column name: IN_PARAMS
data type: 12
VARCHAR2
column return type: 1
column return : In

NOTE :

1. data type(java.sql.Types)

1111 = Types.OTHER

2005 = Types.CLOB

12 = Types.VARCHAR

2. Reference for each col in getProcedureColumns() resultset

String procedureCatalog     = rs.getString(1);
String procedureSchema      = rs.getString(2);
String procedureName        = rs.getString(3);
String columnName           = rs.getString(4);
short  columnReturn         = rs.getShort(5);
int    columnDataType       = rs.getInt(6);
String columnReturnTypeName = rs.getString(7);
int    columnPrecision      = rs.getInt(8);
int    columnByteLength     = rs.getInt(9);
short  columnScale          = rs.getShort(10);
short  columnRadix          = rs.getShort(11);
short  columnNullable       = rs.getShort(12);
String columnRemarks        = rs.getString(13);

3. NOTE that, if package function return CLOB, java will return as Types.OTHER (1111 like above output ).

If we use Types.OTHER in ps.registerOutParameter(), we will face the following error.

org.seasar.framework.exception.SQLRuntimeException: [ESSR0072]SQLException(SQL=[], Message=[Invalid column type], ErrorCode=17004, SQLState=null)

We must pass Types.CLOB into ps.registerOutParameter(), not Types.OTHER.

ref : java2s, mkyong, jguruCodo

Java Exception

Exception Hierarchyรูปภาพ

Catch multiple exception in Java 7

catch(IOException | SQLException | Exception ex){
    logger.error(ex);
    throw new MyException(ex.getMessage());
}

try-with-resource in Java 7

instead of finally close resource

try (MyResource mr = new MyResource()) {
    System.out.println("MyResource created in try-with-resources");
} catch (Exception e) {
    e.printStackTrace();
}

Error Code Example

MyException.java

package com.journaldev.exceptions;
public class MyException extends Exception {
    private static final long serialVersionUID = 4664456874499611218L;
    private String errorCode="Unknown_Exception";
    public MyException(String message, String errorCode){
        super(message);
        this.errorCode=errorCode;
    }
    public String getErrorCode(){
        return this.errorCode;
    }
}

CustomExceptionExample.java

package com.journaldev.exceptions;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class CustomExceptionExample {
    public static void main(String[] args) throws MyException {
        try {
            processFile("file.txt");
        } catch (MyException e) {
            processErrorCodes(e);<
        }
    }
    private static void processErrorCodes(MyException e) throws MyException {
        switch(e.getErrorCode()){
             case "BAD_FILE_TYPE":
                   System.out.println("Bad File Type, notify user");
                   throw e;
             case "FILE_NOT_FOUND_EXCEPTION":
                   System.out.println("File Not Found, notify user");
                   throw e;
             case "FILE_CLOSE_EXCEPTION":
                   System.out.println("File Close failed, just log it.");
                   break;
             default:
                   System.out.println("Unknown exception occured, lets log it for further debugging."+e.getMessage());
                   e.printStackTrace();
         }
    }
    private static void processFile(String file) throws MyException {
        InputStream fis = null;
        try {
             fis = new FileInputStream(file);
        } catch (FileNotFoundException e) {
             throw new MyException(e.getMessage(),"FILE_NOT_FOUND_EXCEPTION");
        }finally{
             try {
                  if(fis !=null)fis.close();
             } catch (IOException e) {
                  throw new MyException(e.getMessage(),"FILE_CLOSE_EXCEPTION");
             }
        }
    }
}

Best practices

1. Throw Early

i.e. instead of

Exception in thread "main" java.lang.NullPointerException
at java.io.FileInputStream.&lt;init&gt;(FileInputStream.java:134)
at java.io.FileInputStream.&lt;init&gt;(FileInputStream.java:97)
at com.journaldev.exceptions.CustomExceptionExample.processFile(CustomExceptionExample.java:42)
at com.journaldev.exceptions.CustomExceptionExample.main(CustomExceptionExample.java:12)

do this

private static void processFile(String file) throws MyException {
     if(file == null) throw new MyException("File name can't be null", "NULL_FILE_NAME");
    //further processing
}

throw early, so we can easily identify the problem

com.journaldev.exceptions.MyException: File name can't be null
at com.journaldev.exceptions.CustomExceptionExample.processFile(CustomExceptionExample.java:37)
at com.journaldev.exceptions.CustomExceptionExample.main(CustomExceptionExample.java:12)

2. Catch Late

the cons of catching exception early

– caller program doesn’t get any notification for the exception

– other applications that might want to process exception in a different manner.

3. Using Custom Exceptions

It’s always better to define exception handling strategy at the design time and rather than throwing and catching multiple exceptions, we can create a custom exception with error code and caller program can handle these error codes. Its also a good idea to create a utility method to process different error codes and use it.

4. Use Exceptions Judiciously

Exceptions are costly and sometimes it’s not required to throw exception at all and we can return a boolean variable to the caller program to indicate whether an operation was successful or not.

For example, while updating the stock quotes in database from a third party webservice, we may want to avoid throwing exception if the connection fails.

5. Document the Exceptions Thrown

Use javadoc @throws to clearly specify the exceptions thrown by the method

full version is at javacodegeeks

[ Java ] Reflection : invoke java method given a method as String

คล้ายๆ eval() ใน Javascript น้ะจ้ะ

ตัวอย่างน้ะจ้ะ เดิมเขียนแบบนี้

SimpleDateFormat sdf = new SimpleDateFormat("ddMMyy");
System.out.println(sdf.format(new Date()));

แต่ถ้าจะเขียนแบบ Reflection จะได้แบบนี้

SimpleDateFormat sdf = new SimpleDateFormat("ddMMyy");
Method m = sdf.getClass().getMethod("format", Date.class);
System.out.println(m.invoke(sdf, new Date()));

ข้างล่าง เป็น ดอกส์ (doc) โดยย่นย่อ ก็อปมาจาก yegor256

method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
method.invoke(obj, arg1, arg2,...);

เพิ่งรู้ว่า จาวาก็ทำอะไรพรรค์นี้ได้ เจ๋งดีเหมือนกันนะ

view detail

javadoc troubleshooting

The below is some problem I faced when I due with javadoc. Therefore, I think it is good to  note it here.

Problem 1

C:\xxx\yyy.java:18: cannot access jxl.Cell
bad class file: C:\aaa\bbb\WEB-INF\lib\jxl.jar(jxl/Cell.class)
class file has wrong version 50.0, should be 49.0
Please remove or make sure it appears in the correct subdirectory of the classpath.
import jxl.Cell;

Solution

Use the right “javadoc” version. In this case we should use javadoc of jdk 6 ( 50.0 ), in stead of jdk 5 ( 49.0 ).

Note that in eclipse, we can set the “Javadoc command” from the “Generate Javadoc” menu.
Use the right javadoc program from there.

Problem 2

and another problem is that some jars may not have the doc attached.

That may affects if we generate the doc from the code that use annotation from the jar that has no doc attached. ( this is related with ‘package-list’ issue ).

The solution is point the -linkoffline to the doc folder, i.e.

-linkoffline file:/D:/sss/ttt/uuudoc . com.wordpress.dsin.mypackagename

VM option for larger heap space

-J-Xmx1024m

Encoding for Another language

-encoding "Shift-JIS" -docencoding "UTF-8" -charset "UTF-8"

[ tomcat ] วิธีใช้ database connection pool (DBCP) จาก JNDI

1. Set up the Tomcat ↔ PostgreSQL side of the connection pool ในไฟล์ web/META-INF/context.xml

<Context path="/hello">
<!-- Link to the local PostgreSQL database -->
<Resource
name="jdbc/postgres"
auth="Container"
type="javax.sql.DataSource"
maxActive="20"
maxIdle="10"
maxWait="5000"
username="tomcat"
password="tomcat"
driverClassName="org.postgresql.Driver"
removeAbandoned="true"
removeAbandonedTimeout="60"
logAbandoned="true"
url="jdbc:postgresql://localhost:5432/tomcat"
validationQuery="select version();"
/>
</Context>

2. ใส่นี่ลงไปในไฟล์ web/WEB-INF/web.xml

ยัดไว้ในแท็ก web-app นะ

<resource-ref>
<description>PostgreSQL Datasource</description>
<res-ref-name>jdbc/postgres</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

3. วิธี pool คือ

import javax.naming.InitialContext;
import java.sql.*;
import javax.sql.*;
...
try {
InitialContext cxt = new InitialContext();
DataSource ds =
(DataSource) cxt.lookup( "java:/comp/env/jdbc/postgres" );
Connection db = ds.getConnection();
PreparedStatement stmt =
db.prepareStatement( "select * from students" );
ResultSet rs = stmt.executeQuery();
writer.println( "<h3>Web nerds:</h3>" );
while ( rs.next() ) {
writer.println( "<p>" + rs.getString( "name" ) +
" is a Web Nerd.</p>" );
}
rs.close();
db.close();
} catch ( javax.naming.NamingException e ) {
writer.println( "<h3>Cannot find PostgreSQL database " +
"connection pool via JNDI!</h3>" );
e.printStackTrace( writer );
} catch ( java.sql.SQLException e ) {
writer.println( "<h3>SQL Exception!</h3>" );
e.printStackTrace( writer );
}

รายละเอียดเพิ่มเติม :

JNDI : http://java.sun.com/javase/6/docs/technotes/guides/jndi/index.html
JNDI tutorial : http://java.sun.com/products/jndi/tutorial/index.html.