2011年6月11日 星期六

spring IoC 使用factoryBean

最近才開使接觸spring IoC ,一般在XML 中設定 的 property 都是使用
......
<bean id="someBean" class="xxx.ooo.ClassName">
 "property name="someField" ref="anotherObject">  
</bean>
......
時都是指定到另一個bean 的,做為參考。換言之一定會存在著
......
<bean id="anotherObject" class="xx.oo.ClassName2">
  ......
</bean>
......

但有時候需要的是用factory的方式產生出來才塞給像上述的 someField的話要怎麼做呢?
上網路上查詢,發現有三個方式。 我自行理解後,筆記如下:
1.用static method 產生物件
2.用一般method產生物件
3.用透過 實作 FactoryBean interface

方法1說明:
以上述的例子來說,假設我們要注入xxx.ooo.ClassName 類別的 someField 欄位,原本是指到anotherObject 這個bean;現在有另一個類別提供一個static method 會產生出someField 需要的物件。

public class StaticFactoryBeanTest {

 public static SomeFieldClass createObject()
 {
               ......
       return someFieldInstance;
 }
}

在XML 中的使用方式為:
<bean id="xx" class="oo.xx.StaticFactoryBeanTest" factory-method="createObject" />


這時候,bean xx 指的就不是 oo.xx.StaticFactoryBeanTest的物件而是 它的static method :createObject 所產生的物件,注意在XML 中要這樣使用,此方法必需為static method

方法2說明:
在XML 中使用方式為:
<bean id="instanceFactoryBean" class="oo.xx.InstanceFactoryBean">
......
</bean>
<bean id="product" factory-bean="instanceFactoryBean" factory-method="createProduct" />
instanceFactoryBean 是一般的bean ,它的類別是oo.xx.InstanceFactoryBean
但 product 它是靠 instanceFactoryBean 的 createProduct 方法產生的物件,所以它的class不是oo.xx.InstanceFactoryBean,而是看createProduct 產生了什麼。

方法3說明:
在XML 中使用方式為:
<bean id="product" class="oo.xx.MyFactoryBean" />
oo.xx.MyFactoryBean 是implements org.springframework.beans.factory.FactoryBean 這個interface
而FactoryBean 有三個method 分別是:
public Object getObject();
public Class getObjectType();
public boolean isSingleton();

而這個product 注入的是 oo.xx.MyFactoryBean 的getObject()方法產生的物件,並非是oo.xx.MyFactoryBean這個類別的instance

2011年6月3日 星期五

spring 使用 application 中定義的 properties

問題:
在applicationContext 中常會設定一個properties 來載入一些設定檔
通常是
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
.....
</bean>

但發現 這個 PropertyPlaceholderConfigurer 類別不提供它的 java.util.Properties 讓我們用。
但是它的父類別org.springframework.core.io.support.PropertiesLoaderSupport 有提供一個protected method
protected Properties mergeProperties() throws IOException

所以這邊提供一種做法是,自己寫一個Class 繼承 PropertiesLoaderSupport ,然後裡面提供一個method

public class MyPropertyPlaceholderConfigurer extends
  PropertyPlaceholderConfigurer {

  Properties mergedProperties;

   public Properties getMergedProperties() throws IOException {
     if (mergedProperties == null) {

       mergedProperties = mergeProperties();

     }
     return mergedProperties;

   }
}

然後 applicationContext 裡的 propertyConfigurer設定改成
<bean id="propertyConfigurer" class="MyPropertyPlaceholderConfigurer">

......
這樣就可以在之後使用這個bean 取得 properties

由Spring 取得 Jboss JNDI datasource

問題:非一般由web container 取得JDNI 的方式。而是一隻獨立程式需要存取DB,要從JBoss取得JNDI datasource 。
解決方式:

在 applicationContext中
原本會有


...
 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref="jdbcDataSource"/>
</bean>
<bean id="jdbcDataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource"
...>
...
這是使用jdbc的方式連的

加上
<bean id="jndidataSource"  class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="your_JNDI_name"/>
<property name="resourceRef" value="false"/>
<property name="jndiTemplate" ref="jndiTemplate" />
</bean>
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
<prop key="java.naming.provider.url">jnp://your_JBoss_IP:1099</prop>
<prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop>
<prop key="jnp.disableDiscovery">true</prop>
</props>
</property>


然後在執行這隻獨立的jar 檔時,加上jboss 的jar 檔到 classpath中

for example:
java  -cp /...[jboss home].../jboss-as/client/jbossall-client.jar:yourJarFile.jar your.main.class
不過這個方式要JDNI,好久啊~久到爆炸,在自己的localhost 跑都要超過兩分鐘 orz

Cron Job 出現亂碼問題

問題: java file 丟到 linux 下執行有遇到io處理都好好的。但同一隻程式用 cron job 跑,有io 的部份就出現亂碼。

解決方法:
example.sh 範例
LC_ALL=zh_TW.UTF-8
LANG=zh_TW.UTF-8
/....[java path]..../java -Dfile.encoding=UTF-8 -jar yourJava.jar


這樣就能解決IO出現亂碼的問題了。

2011年5月11日 星期三

sybase SQL 取得當週星期一(get Monday)

背景說明:要取得當周第一天。(通常系統都是把星期天設為當週第一天)所以一般來說,只要呼叫一個 類似  weekday 之類的函數得出目前是 當周的第 n 天,然後把目前日減掉 n即可。

問題: 以星期一做為一周的第一天。帶入日期取得當週第一天。
原本將日期帶入 weekday 的函數得到的 數字  1~7 直接減的話,得到的日期是星期天。

2011年5月10日 星期二

jQuery UI datepicker 1.8.12 日期輸入限制

jQuery UI datepicker 很方便的讓一個input element 可以有calendar做為協助輸入的ui,不過有時候,要validate 輸入的日期資料時,理想的方式之一就是不要讓不想輸入的資料出現。
舉例來說,如果只想讓使用者輸入 星期一 的日期,其它的日期都不要出現的話。該怎麼做?

jQuery UI datepicker 1.8.12 顯示問題

jQuery datepicker 1.8.12 使用發現一個問題 就是 z-index 每次都會被自動設成 1,如果畫面上有 z-index 大於1的,就有可能被蓋住。

解決方法:一種是設一個很大的數字,另一方式,就是找出目前頁面中z-index 最大的element 然後再設比它大一點。
看起來後者是比較完善的解決方法。要做到此點,請參考下列步驟:

2011年5月1日 星期日

sybase 取得月天數

如何使用SQL ,代入日期,取得當月天數? 例: 傳入 1/23  return 31,傳入  2/10 return 28(潤年29)

javascript 取得 月天數

function daysInMonth(iMonth, iYear)
{
    return 32 - new Date(iYear, iMonth, 32).getDate();
}

iMonth:0~11
iYear:西元年 yyyy

原理說明:
new Date(iYear, iMonth, 32) ,會依 年月日,產生一個日期,但是日期超過該月的部份會使產生的日期變成下個月的日期
舉例:
new Date(2011, 0, 32) ,是指要產生一個日期是 2011年1月32號的,但是因為1月只有31天,所以產生出來的時間變成是2011年2月1號,也就是自動幫你進位了。
產生出來的日期再用 .getDate()取得 "日" 的部份,最後用 32 去減。 換句話說,用32代入產生的日期不管是代到哪個月都會進位,進位後的日數,可能是1 ~ 4 不等,也就是說原本的月份日數是比32 少 1~4不等。 所以用32減去,就是所求。

變通一下,把function 內的兩個32 改成是 35或是其它 >31 但 <60 的數也是可以,只要不要讓它再次進位到下個月執行的意義和原做法就是一樣的。

參考:http://snippets.dzone.com/posts/show/2099