Friday, July 5, 2013

Create a keystore (Certificate) and then sign jar (applet)

To sign a jar
  1. Need to create a keystore (like Certificate)
    1. Go to your java jdk directory (e.g. C:\Program Files\Java\jdk1.6.0_25\bin)
    2. Type keytool -genkey -keystore icepdfapplet.keystore -alias icepdfapplet -keyalg RSA where icepdfapplet.keystore will be created
    3. You will be asked for Name, Unit... and password (Please remember the password)
    4. The keystore will be successfully created
  2. Now assign the certificate to the jar
    1. Type jarsigner -keystore icepdfapplet.keystore -storepass 123456789 icepdf-applet.jar icepdfapplet where 123456789 is the password I entered in the previous and icepdf-applet.jar is the jar file being assigned with the certificate
>keytool -genkey -keystore icepdfapplet.keystore -alias icepdfapplet -keyalg RSA
>jarsigner -keystore icepdfapplet.keystore -storepass 123456789 icepdf-applet.jar
icepdfapple

Thursday, July 4, 2013

"ant" is not recognized as an internal or external command

If you find that you run ant command in command prompt, there is an error that "ant" is not recognized as an internal or external command,

Please do the following steps.
  1. Download the apache-ant binary distributions zip file and unzip it under C:\bin directory
  2. Edit the computer environment variable (Right click My Computer and select properties > Advance > Environment Variable)
  3. Add C:\bin\apache-ant\bin in Path Variable
When open a command console, and type echo PATH. You will see the newly added path C:\bin\apache-ant\bin

Monday, April 22, 2013

SQL Exception 17009 - Closed Statement

花了一段時間去 investigate 個 SqlException with Error code '17009'.

我主要用 dbcp 作 datasource, spring 3.1 既 aop 做 declarative transaction management 同 mybatis 既 SqlSessionDaoSupport, 用SqlSessionDaoSupport是因為我有機會在 DAO Implementation 做一些 java coding.

我個development condition:
1) Spring 3.1.0
2) Spring Security 3.2.0
3) Vaadin 6.8.2
4) Spring-Mybatis 1.1.1
5) MyBatis 3.2.0
6) Java 5+
7) Oralce 10g

我是沒有用 annotation. 主要原因是方便和清楚知道每個 manager 的關係.

在 spring 的 config. file 裡,加上以下的codes.

<!-- Configure your datasource -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="${db.driverClassName}" />
        <property name="url" value="${db.url}" />
        <property name="username" value="${db.username}" />
        <property name="password" value="${db.password}" />
        <property name="defaultAutoCommit" value="false" />
        <property name="poolPreparedStatements" value="true" />
 <property name="maxOpenPreparedStatements" value="50" />
 <property name="validationQuery" value="select 1 from dual"/>
</bean>

<!-- Configure a SQL session for SQL execution in DAO layer -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
 <property name="dataSource" ref="dataSource" />  
 <property name="configLocation" value="classpath:mybatis-config.xml"/>  
</bean>

<!-- Use AOP to set the transaction management -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  <property name="dataSource" ref="dataSource" />  
</bean>
<aop:config>
    <aop:pointcut id="transactionService" expression="execution(* com.gpch.cams.service.*Manager.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionService" order="1"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>         
            <tx:method name="get*" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>                        
        </tx:attributes>
</tx:advice>

<!-- set sqlSessionFactory for your DAO -->
<bean id="employeeDao" class="com.gpch.cams.dao.impl.EmployeeDaoImpl">
 <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

<!-- In your java class (e.g. EmployeeDaoImpl) -->
<!-- must extend SqlSessionDaoSupport -->
<!-- use getSqlSession() to call and execute your MyBatis Sql -->
public class EmployeeDaoImpl extends SqlSessionDaoSupport implements EmployeeDao{

    public Employee getEmployee(Long empId){
          return (Employee) getSqlSession().selectOne("getEmployeeRecordById", empId);
    }
}



一開波run 個program 都冇事, 做insert 都係冇事, 但run run 下就出現以下的exception. 找了一段時間, 仲要係間歇性出現. 最後發現用錯了jars. 應該用 common-dbcp-1.2.2.jar and common-pool-1.4.jar

2013-04-22 10:44:42,665 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Finished creating instance of bean 'Sybase'
2013-04-22 10:44:42,665 INFO [org.springframework.jdbc.support.SQLErrorCodesFactory] - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]
2013-04-22 10:44:42,665 DEBUG [org.springframework.jdbc.support.SQLErrorCodesFactory] - Looking up default SQLErrorCodes for DataSource [org.apache.commons.dbcp.BasicDataSource@2596c1]
2013-04-22 10:44:42,665 DEBUG [org.springframework.jdbc.support.SQLErrorCodesFactory] - Database product name cached for DataSource [org.apache.commons.dbcp.BasicDataSource@2596c1]: name is 'Oracle'
2013-04-22 10:44:42,665 DEBUG [org.springframework.jdbc.support.SQLErrorCodesFactory] - SQL error codes for 'Oracle' found
2013-04-22 10:44:42,665 DEBUG [org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator] - Unable to translate SQLException with Error code '17009', will now try the fallback translator
2013-04-22 10:44:42,665 DEBUG [org.mybatis.spring.SqlSessionUtils] - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40d241]
2013-04-22 10:44:42,665 DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Initiating transaction rollback
2013-04-22 10:44:42,665 DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Rolling back JDBC transaction on Connection [jdbc:oracle:thin:@localhost:8081:oral, UserName=test, Oracle JDBC driver]
2013-04-22 10:44:42,744 DEBUG [org.mybatis.spring.SqlSessionUtils] - Transaction synchronization rolling back SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40d241]
2013-04-22 10:44:42,744 DEBUG [org.mybatis.spring.SqlSessionUtils] - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40d241]
2013-04-22 10:44:42,744 DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Releasing JDBC Connection [jdbc:oracle:thin:@localhost:8081:oral, UserName=test, Oracle JDBC driver] after transaction
2013-04-22 10:44:42,744 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
Other Threads:
https://forums.oracle.com/forums/thread.jspa?messageID=10509456
https://issues.apache.org/jira/browse/DBCP-28

Tuesday, March 26, 2013

iReport 4.0.1 - Connect DB with iReport

 To create a new DB connection into iReport

  • 選擇 "Window" and select "Services" 去開著 "Services" 視窗
  • 選擇 "Databases" in "Services" , 然後 right click and select "New Connection"
  • 選擇 "New Driver" for "Name"
  • 加 ojdbc14.jar 
  • 輸入 User Name, Password 和 JDBC URL

 To Add data source from existing DB connection

  • 選擇 Report datasources
  • Click "New"
  • Select Database JDBC connection
  • And then input the correct information.


Friday, March 1, 2013

Linux Concepts

讀大學的時候,主要學習寫程式的概念,對於伺服器那方面東西不太清楚.出來工作後,很多時要configure servers (e.g linux)

要趁早學多一點,免得用起上來來個措手不及.

以下這個綱頁做得幾好,因許多時的 Tutorial 都是教寫 command 而忽略了背後的意義,原因和運作.但這個綱頁主要講述 concept 的東西!

http://www.linux-tutorial.info/modules.php?name=MContent&pageid=224

對我來說,寫唔難,Configure 唔難,最難是採用那一個方法是最好,或者的怎樣解決!寫同configure都係 syntax 野,每個 programmer 只要 google 一下就會找到答案,但 methods 就唔同,是 concept 野,因為你要識這樣東西才能在某指定的情況下提出最合適的解決方法.

希望在這年裡有多一點時間去不斷增值自己!加油!

Monday, February 18, 2013

Java VisualVM to monitor memory

Condition: You want to monitor the java heap size in your local PCs or remote servers. You could use Java VisualVM tool if your device (local PCs or remote servers) must have jdk1.5+ for program execution. For Unix and Linux, they must install X-windows first.

Step to run the Java VisualVM.
  1. echo "%JAVA_HOME%"
    (To show your installed JDK path. e.g. C:\Program Files\Java\jdk1.6.0_25\bin)
  2. cd "%JAVA_HOME
    (Go to your JDK bin)
  3. jvisualvm.exe
    (Run Java VisualVM tool)
According to the following picture, you will see that 3 Java Applications are running on my PC. They are
  1. Unknow Application (pid 3164)
  2. JDeveloper 11g (pid 248)
  3. Tomcat (pid 3560)

Double the java application you want to monitor. I chose Tomcat as an example. You can select Monitor, Threads, Sampler and Profiler tabs to view the statistic.

To monitor remote server (JBOSS), you could
  1. Right click "Remote" and select "Add Remote Host..."
  2. Input your Host Name such as 192.168.254.111
  3. Click "Advanced Settings" and input Post 2020 (jstsd port - RMI Broadcasting - Listener) and set the Refresh Interval
  4. Then you will see 192.168.254.111 under remote
  5. Right click 192.168.254.111 and select "Add JMX Connection"
  6. Input Port "1090" (JMX port setting in Jboss - Check your server setting)
  7. Input Username and password
My Personal Jboss Testing Server Setting
  • JMX port in JBoss server : 1090
  • jstatd port in JBoss server : 2020
  • jstatd port in local (PC) Tomcat server (your IP) should be as default

Monday, February 4, 2013

Vaadin 6.8 with EmbedPDF

Introduction: 

Environment:
Vaadin 6.8 + AppletIntegration 1.2.9 (Add-on)
Spring-Security 3.1.2
Spring 3.1.0
EmbedPDF.jar (Version: 0.18)

Condition: 

Due to business requirement, it only allows users to print PDF. No save function will be provided at all. (That means: No PDF file will be created at the Local directory)

I tired to find the solution on the internet but no suitable methods for me. Therefore, I used the EmbedPDF Applet instead of Adobe Reader to view PDF.

There are several steps that will be gone through in details:
  1. Add Vaadin addon AppletIntegration (not describe in details)
  2. Add the EmbedPDF Applet into your Vaadin Web Application
  3. Configure your Spring-Security file

Add the EmbedPDF Applet into your Vaadin Web Application

  1. Create a directory named "applet" under your WebContent/VAADIN/  It is because files under /WEB-INF directory are protected. It is not allowed to be directly accessed by users.
  2. Place your EmbedPDF.jar and a PDF file into "applet" directory 
  3. In your source code, please pay attention to 
    • AppletClass - it always be "EmbedPDF.class"
    • Codebase - it is the directory your EmbedPDF.jar placed into
    • AppletParams - they are the parameters being passed into the EmbedPDF applet
      • Please kindly refer to the EmbedPDF Specification Readme file. There are some parameters must be set.
     
    VerticalLayout x = new VerticalLayout();
    AppletIntegration applet2 = new AppletIntegration(){  
         private static final long serialVersionUID = 7124868233557401171L;  
         @Override  
         public void attach(){  
             setAppletArchives(Arrays.asList(new String[]{"EmbedPDF.jar"}));  
             setCodebase("/ProjectName/VAADIN/applet/");     
             setAppletClass("EmbedPDF.class");  
             setAppletParams("id", "embedId");  
             setAppletParams("pdf", "/ProjectName/VAADIN/applet/example.pdf");  
             setAppletParams("enableOpenWindow", "false");  
             setWidth("500px");  
             setHeight("500px");  
         }  
     };  
     x.addComponent(applet2);  
     getApplication().getMainWindow().addWindow(x);  
    
The file structure

Configure your Spring-Security file

  1. It is required to make the /VAADIN/applet/ directory to be Anonymously. It is because a new session will be created when the EmbedPDF applet is called. So, the spring security go through the authentication. It is required to pass the username and password to the spring security for the authentication process. There is an exception thrown in the app. server since spring security cannot get the username and password. So, it will block the EmbedPDF.jar and EmbedPDF.class to run. 
  2. There lists some exceptions will be found if the spring security setting is not correct
    • java.lang.ClassFormatError: Truncated class file
    • java.lang.ClassFormatError: Incompatible magic value 537528892 in class file
 <http auto-config="false" entry-point-ref="authenticationEntryPoint"   
     access-denied-page="/jsp/login_error" use-expressions="true">  
     <intercept-url pattern="/jsp/login*" access="permitAll" />  
     <intercept-url pattern="/jsp/login_error*" access="permitAll" />  
     <intercept-url pattern="/VAADIN/applet/**" access="permitAll" />  
     <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />  
     <logout invalidate-session="true"/>  
     <custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER"/>  
 </http>  

Addition Information: Delete the dynamic generated PDF file

  1. The following code describe how to get the absolute path in java for server
  2. It is better to use a helper to create a PDF file and return a new AppletIntegration
  3. When user removes the Applet from the layout, the remove will be deleted (see the "detach" function)

//TODO: create your own file

VerticalLayout x = new VerticalLayout();
final String filename = "example.pdf";
final String absReportzPath = String absProjPath = ((WebApplicationContext)ProjectApplication.getInstance().getContext())
 .getHttpSession().getServletContext().getRealPath("/VAADIN/reportz/reportz/");

AppletIntegration applet2 = new AppletIntegration(){  
     private static final long serialVersionUID = 7124868233557401171L;  
     @Override  
     public void attach(){  
         setAppletArchives(Arrays.asList(new String[]{"EmbedPDF.jar"}));  
         setCodebase("/ProjectName/VAADIN/applet/");     
         setAppletClass("EmbedPDF.class");  
         setAppletParams("id", "embedId");  
         setAppletParams("pdf", "/ProjectName/VAADIN/applet/reportz/"+filename);  
         setAppletParams("enableOpenWindow", "false");  
         setWidth("500px");  
         setHeight("500px");  
     }  

     @Override
     public void detach(){ //To delete file if the applet is removed.
         String absPath = getAbsoluteReportzDirectory();
         File delFile = new File(absReportzPath+"/"+fileName);
         if(delFile.exists()){
             delFile.delete();
         }
     }
 };  
 x.addComponent(applet2);  
 getApplication().getMainWindow().addWindow(x);