Archive for August 2008
The encoding chain
UTF-8 charset is normally used as default in all the components of a Java software system from database to web browser. Refer these links in order to get information about it.
However, external files can be served by other systems in any charset different to UTF-8. To preserve encoding chain, file reading must be done specifying external charset in these terms.
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class TestEncoding {
public static void processFile(String filename, String charset) throws IOException {
FileInputStream fstreamIn = new FileInputStream(filename);
DataInputStream in = new DataInputStream(fstreamIn);
// Specify charset for the InputStream
BufferedReader br = new BufferedReader(
new InputStreamReader(in, charset));
String strLine;
while ((strLine = br.readLine()) != null) {
// Do something with the line: insert into database, ...
}
fstreamIn.close();
}
public static void main(String...strings) throws IOException {
String filename = "/hosts/data.input";
String charset = "ISO-8859-15";
processFile(filename, charset);
}
}
Loading Spring context and its consequences
Let’s say we have an application trying to insert a row on some table. Using Spring JDBC techniques, we must define one Spring XML context file as next.
< ?xml version="1.0" encoding="UTF-8"?>
< !DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="datasource"
class="org.springframework.jdbc.datasource.SingleConnectionDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:SID" />
<property name="username" value="user" />
<property name="password" value="pass" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource"><ref local="datasource" /></property>
</bean>
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager"><ref bean="transactionManager" /></property>
</bean>
<bean id="someDAO" class="es.foo.db.dao.ComercioDAO" />
</beans>
We can define too a class in order to simplify the process of getting transactions and DAOs from Spring Context. Below two alternatives are shown: DBManager class and StaticDBManager class.
DBManager is coded in a dynamic way…
public class DBManager {
private ClassPathResource resource;
private XmlBeanFactory xmlFactory;
public DBManager() {
resource = new ClassPathResource("/es/foo/db/spring-config.xml", DBManager.class);
xmlFactory = new XmlBeanFactory(resource);
}
public JdbcDaoSupport getDAO(String daoName) {
DataSource dataSource = (DataSource)xmlFactory.getBean("datasource");
JdbcDaoSupport dao = (JdbcDaoSupport)xmlFactory.getBean(daoName);
dao.setDataSource(dataSource);
return dao;
}
public TransactionTemplate getTransactionTemplate() {
return (TransactionTemplate)xmlFactory.getBean("transactionTemplate");
}
}
… while StaticDBManager is coded in a static way.
public class StaticDBManager {
public static JdbcDaoSupport getDAO(String daoName) {
ClassPathResource resource = new ClassPathResource("/es/foo/db/spring-config.xml", StaticDBManager.class);
XmlBeanFactory xmlFactory = new XmlBeanFactory(resource);
DataSource dataSource = (DataSource)xmlFactory.getBean("datasource");
JdbcDaoSupport dao = (JdbcDaoSupport)xmlFactory.getBean(daoName);
dao.setDataSource(dataSource);
return dao;
}
public static TransactionTemplate getTransactionTemplate() {
ClassPathResource resource = new ClassPathResource("/es/foo/db/spring-config.xml", StaticDBManager.class);
XmlBeanFactory xmlFactory = new XmlBeanFactory(resource);
return (TransactionTemplate)xmlFactory.getBean("transactionTemplate");
}
}
Without thinking of it deeply, we can imagine both solutions working in the same way.
public class SpringDBTest {
class DoWork implements TransactionCallback {
private DBManager db;
public DoWork(DBManager db) {
this.db = db;
}
public Object doInTransaction(TransactionStatus ts) {
SomeDAO someDAO = (SomeDAO) db.getDAO("someDAO");
someDAO.insert();
return null;
}
}
public static void main(String... args) throws Exception {
// Test 1 - Load Spring Context once
DBManager db = new DBManager();
TransactionTemplate ttDynamic = db.getTransactionTemplate();
ttDynamic.execute(new SpringDBTest().new DoWork(db));
// Test 2 - Load Spring Context statically twice
TransactionTemplate ttStatic = StaticDBManager.getTransactionTemplate();
ttStatic.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus ts) {
try {
SomeDAO someDAO = (SomeDAO) StaticDBManager.getDAO("someDAO");
someDAO.insert();
} catch (RuntimeException re) {
ts.setRollbackOnly();
re.printStackTrace();
}
return null;
}
});
}
}
However, running the code, no rollback is performed on Runtime Exception for Test 2.
This behavior is caused by Spring Context load in StaticDBManager class. Doing the initialization so, two different instances of datasource object are generated (one for the transaction and another one for the DAO) due to Spring Injection mechanism. So, in Test 2, transactional context is lost on execution.
Using Portecle to replace command line Keytool interface
Usually default keytool from Sun’s JDK is used to perform local testing on applications involving crytographic operations. Portecle is a nice alternative to achieve a Windows-like behaviour of this tool. It can be launched writing a simple CMD script and executing it from desktop.
START javaw -jar C:\portecle-1.3\portecle.jar EXIT