云自無心水自閑

          天平山上白云泉,云自無心水自閑。何必奔沖山下去,更添波浪向人間!
          posts - 288, comments - 524, trackbacks - 0, articles - 6
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          2月25日,IBatis3發(fā)布了Beta10,在主頁上宣稱,一個月來Beta9的公測都沒有收到真正的Bug提交。
          所有收到的問題都是新的功能要求。
          所以,如果沒有意外的話,Beta10將會用于投票表決是否作為GA(General Available)版本。

          posted @ 2010-03-08 19:50 云自無心水自閑 閱讀(1757) | 評論 (1)編輯 收藏

          在教程的第四部分(http://www.aygfsteel.com/usherlight/archive/2009/06/20/283396.html)我們已經(jīng)粗略地介紹了Tapestry的前綴,其中提及最常用的兩種literal和prop。這里順便再介紹一下其他的幾個前綴.
          1、context,這個經(jīng)常在引用圖片的時候用到。比如:<img src="${context:images/icon.png}"/> 這樣就能夠在頁面上顯示在web-inf/images/icon.png
          2、message,這個是需要I18N的應用必用的前綴。${message:some-key}
          3、var,用于定義生成一個臨時變量。比如:<li t:type="loop" source="1..10" value="var:index">${var:index}</li>。如果沒有加這個前綴var:的話,就需要在頁面類中添加一個property: index以及相應的getter和setter。
          我們這次介紹自定義一個cycle前綴,這個可以用于在表格中顯示不同背景的行(也就是斑馬條)。
          比如:
          <t:grid ....  rowClass="cycle:line1,line2">
          ...
          </t:grid>
          或者
          <t:loop ...>
          <div class="${cycle:line1,line2}">aaaa</div>
          </tloop>

          自定義prefix一般來說是3個步驟,
          1、定義一個BindingFactory,這個需要實現(xiàn)BindingFactory接口
          2、定義一個Binding繼承AbstractBinding
          3、注冊這個Binding

          看一下具體的prefix的類:

           1import java.util.ArrayList;
           2import java.util.List;
           3
           4import org.apache.tapestry5.Binding;
           5import org.apache.tapestry5.BindingConstants;
           6import org.apache.tapestry5.ComponentResources;
           7import org.apache.tapestry5.ioc.Location;
           8import org.apache.tapestry5.services.BindingFactory;
           9import org.apache.tapestry5.services.BindingSource;
          10
          11/**
          12 * Implementation of the cycle: binding prefix -- we parse list of bindings
          13 * and generate delegate bindings for each element<br>
          14 * default binding is literal, other bindings can be used by specifying prefix.<br>
          15 * example: "cycle:prop:name,prop:lastName,sth,sth else"
          16 */

          17public class CycleBindingFactory implements BindingFactory {
          18    private final BindingSource _bindingSource;
          19
          20    public CycleBindingFactory(BindingSource source){
          21        this._bindingSource = source;
          22    }

          23    
          24    public Binding newBinding(String description, ComponentResources container, ComponentResources component,
          25            String expression, Location location)
          26    {
          27        List<Binding> delegates = new ArrayList<Binding>();
          28        String[] bindingNames = expression.split(",");
          29
          30        for (String bindingName : bindingNames){
          31            String defaultBinding = BindingConstants.LITERAL;
          32
          33            Binding binding = _bindingSource.newBinding(description, container, component, defaultBinding, bindingName, location);
          34            delegates.add(binding);
          35        }

          36        
          37        CycleBinding cycleBinding = new CycleBinding(delegates);
          38        container.addPageLifecycleListener(cycleBinding);
          39            
          40        return cycleBinding;
          41    }

          42}

           1import java.util.List;
           2
           3import org.apache.tapestry5.Binding;
           4import org.apache.tapestry5.internal.bindings.AbstractBinding;
           5import org.apache.tapestry5.runtime.PageLifecycleListener;
           6
           7
           8public class CycleBinding extends AbstractBinding implements PageLifecycleListener{
           9    private final List<Binding> delegates;
          10    private int index = 0;
          11
          12    public CycleBinding(List<Binding> delegates) {
          13        this.delegates = delegates;
          14    }

          15
          16    public Object get() {
          17        Object ret = delegates.get(index).get();
          18        index ++
          19        if(index>=delegates.size()) index = 0;
          20        return ret;
          21    }

          22    
          23    @Override
          24    public boolean isInvariant() {
          25        return false;
          26    }

          27    
          28    @Override
          29    public Class<Object> getBindingType() {
          30        return Object.class;
          31    }

          32
          33
          34    public void containingPageDidDetach() {
          35        index=0;
          36    }

          37
          38    public void containingPageDidAttach() {/*not interested*/}
          39    
          40    public void containingPageDidLoad() {/*not interested*/}
          41}

          Binding和BindingFactory寫好了,注冊后就可以使用了,注冊的過程是在AppModel中添加以下一段代碼:
          1    public static void contributeBindingSource(
          2            MappedConfiguration<String, BindingFactory> configuration,
          3            BindingSource bindingSource
          4            )
          5    {
          6        configuration.add("cycle",new CycleBindingFactory(bindingSource));
          7    }
           


          posted @ 2010-03-06 15:54 云自無心水自閑 閱讀(2255) | 評論 (0)編輯 收藏

          1. 先開始看SpringSide吧。
          主要看寒冬日志版3.2.1開始有的JMS演示和WebService演示

          posted @ 2010-03-01 12:24 云自無心水自閑 閱讀(405) | 評論 (0)編輯 收藏

          一直覺得EJB好像已經(jīng)日薄西山了,但是實際上生命力還挺頑強的。
          另外,還有Web Service, SOA這個概念還是有人相信的。

          所以,延伸項目有:JMS, MQ

          posted @ 2010-03-01 12:21 云自無心水自閑 閱讀(387) | 評論 (0)編輯 收藏

          我記得好像是Appfuse的作者曾經(jīng)這樣評價過Tapestry:只要你真正掌握了Tapestry,你的開發(fā)效率將會得到極大的提高。為什么呢?我認為他這樣說的一個重要原因就是Tapestry的組件機制。Tapestry提供了非常便利的組件定義機制,隨著Tapestry的組件不斷積累,Tapestry的開發(fā)將會變得越來越簡單。
          本文就用一個實例來看一下Tapestry中是如何添加一個自定義組件的。
          Tapestry的內(nèi)置組件只提供了checkbox,而且只能返回一個boolean,用于表明是否被選中。
          比如,要進行一個群眾喜愛的水果調(diào)查,選項有: 蘋果,葡萄,桃子,香蕉...,就需要對應每個選項設置一個布爾型變量,顯得比較繁瑣。
          這里我們將添加一個組件用于將一組checkbox集中起來返回一個逗號分隔的字符串值。
          通過查看Tapestry中的checkbox的源碼(已經(jīng)附在文章的后面)可以知道,Tapestry可以很容易地通過Request來獲取Form中的變量的值。
          遇到的問題:
          Tapestry的checkbox組件不允許設置相同的name,如果name相同,Tapestry會自動在name后面添加后綴來使之不同。
          If a component renders multiple times, a suffix will be appended to the to id to ensure uniqueness(http://tapestry.apache.org/tapestry5.1/tapestry-core/ref/org/apache/tapestry5/corelib/components/Checkbox.html)。如果各checkbox的name不同,我們無法通過request來獲得一組checkbox的值。
          思路:
          在頁面模板中不使用tapestry的checkbox組件,而使用Html的checkbox,這樣可以避免tapestry自動修改checkbox的name。
          添加一個新的tapestry組件,來映射接受所有同名的checkbox的值,并把值返回給tapestry頁面中對應的變量。這個組件需要有一個屬性,這個屬性的值就是所有同組checkbox的name,這樣,這個組件就可以通過Request來獲取所有相同name的checkbox的值。
          代碼:
           1 public class CheckBoxGroup extends AbstractField {
           2 
           3     @SuppressWarnings("unused")
           4     @Parameter(required = true, autoconnect = true)
           5     private String value;
           6 
           7     @Parameter(required = true, autoconnect = true)
           8     private String groupName;
           9 
          10     @Inject
          11     private Request request;
          12 
          13     @SuppressWarnings("unused")
          14     @Mixin
          15     private RenderDisabled renderDisabled;
          16 
          17     @Inject
          18     private ComponentResources resources;
          19 
          20     @BeginRender
          21     void begin(MarkupWriter writer)
          22     {
          23         writer.element("input""type""checkbox",
          24                        "name", groupName,
          25                        "id", getClientId(),
          26                        "style""display:none");
          27 
          28         resources.renderInformalParameters(writer);
          29 
          30         decorateInsideField();
          31     }
          32 
          33     @AfterRender
          34     void after(MarkupWriter writer)
          35     {
          36         writer.end(); // input
          37     }
          38 
          39     @Override
          40     protected void processSubmission(String elementName)
          41     {
          42         String elementValue = "";
          43         String[] valueArray = request.getParameters(groupName);
          44         if ( valueArray != null && valueArray.length > 0 ) {
          45             elementValue = valueArray[0];
          46             for ( int i = 1; i < valueArray.length; i ++ ) {
          47                 elementValue += "," + valueArray[i];
          48             }
          49         }
          50         value = elementValue;
          51     }
          52 }

          組件的使用:
          -----tml------
          <t:CheckBoxGroup t:groupName="literal:bookId" t:value="selectedBooks"/>
          <t:loop source="bookList" value="book" encoder="encoder">
              <div><input type="checkbox" name="bookId" value="${book.id}"/> ${book.name}</div>
          </t:loop>
          注意checkBoxGroup的groupName和其他checkbox的name必須一致,checkBoxGroup的value的值就是頁面中的變量名

          -----java-----
              @SuppressWarnings("unused")
              @Property
              private final ValueEncoder<Book> encoder = new ValueEncoder<Book>() {
                  public String toClient(Book value) {
                      return String.valueOf(value.getId());
                  }
                  public Book toValue(String clientValue) {
                      return bookDao.getBook(Integer.parseInt(clientValue));
                  }
              };
             
              public List<Book> getBookList() {
                  return bookDao.getBooks();
              }
             
              @SuppressWarnings("unused")
              @Property
              private Book book;
             
              @SuppressWarnings("unused")
              @Property
              private String selectedBooks;





          posted @ 2010-02-12 07:26 云自無心水自閑 閱讀(3311) | 評論 (3)編輯 收藏

          在tapestry5中,在頁面之間傳遞基本有3種方法
          1、存放在Session中
          2、使用@Persist進行持久化
          3、使用頁面context來傳遞參數(shù)。
          其中1和2都需要將數(shù)據(jù)存放在Session中,相對來說系統(tǒng)的開銷比較大。尤其是多用戶高并發(fā)情況下,對于性能可能會有一定的影響。
          使用頁面Context來傳遞則需要在開發(fā)時寫一些代碼,增加了一些開發(fā)量,顯得沒有前兩種方法方便。
          第3種方法的實現(xiàn)是需要在頁面中添加onActivate和onPassivate方法來完成頁面參數(shù)的傳遞。
          我們先來看一下其背后的故事。
          舉個例子,比如說我們有兩個頁面,第一個是查詢條件輸入頁面input,另一個是查詢結(jié)果輸出頁面output。input頁面中有兩個查詢條件,起始時間dateFrom和終止時間dateTo
          在Input.java中,我們可以很直觀地這樣寫:
          @InjectPage
          private Output output;

          @Property
          private String dateFrom;

          @Property
          private String dateTo;

          Object onFormSubmit() {
                  output.setDateFrom(dateFrom);
                  output.setDateTo(dateTo);
                  return output;
          }
          首先使用注解注入output頁面,然后在表單的提交事件中,返回output,這樣就在程序中定義了返回頁面,而不是使用配置文件的方式。
          但是這樣的實現(xiàn)卻不能正確運行,原因是因為Tapestry5的使用了頁面池技術,頁面在每次渲染前都是從頁面池中隨機獲取一個頁面,而從頁面池中取得的頁面,所有的屬性都是被清空了的。
          也就是說在上例中,雖然我們注入了output頁面,但是此頁面馬上就被放入了頁面池,而且其中的屬性值馬上就被清空了。這就是引入onActivate和onPassivate這丙個方法的原因。tapestry5在清空屬性前會首先查看是否包含onPassivate方法,如果有,就把其返回值保存起來,然后從頁面池中取得頁面后,再把剛才保存的值作為參數(shù)傳遞給onActivate方法。
          這就是方法3的基本原理,但是無論是在官方的文檔或是示例或者網(wǎng)上其他的應用中,可以發(fā)現(xiàn)大部分都是使用單個參數(shù)的,比如說id。這也很容易理解,因為onPassivate的方法的返回值只能有一個。
          在Tapestry5的官方文檔中,只有一句非常簡要的話介紹了如果傳遞多個文檔的方法: The activation context may consist of a series of values, in which case the return value of the method should be an array or a List. (參見:http://tapestry.apache.org/tapestry5.1/guide/pagenav.html)。
          但是這并不是說只要在onPassivate中把參數(shù)的值加入到List中,返回一個List,而在onActivate中接受一個List參數(shù),然后就可以得到其中的參數(shù)了,因為Tapestry5把參數(shù)傳給onActivate的方法其實是通過將參數(shù)作為HttpRequest中的參數(shù)的。如果試圖使用上述方法就是得到一個“無法將List轉(zhuǎn)換成String的錯誤”
          所以方法應該是這樣的,在Output中:

          private List<String> paramList;
          public void setParamList(List<String> paramList) {
                  this.paramList = paramList;
          }
          public List<String> getParamList() {
                  return paramList;
          }
          List<String> onPassivate() {
                  return paramList;
          }
          void onActivate(String dateFrom, String dateTo) {
                  this.dateFrom = dateFrom;
                  this.dateTo = dateTo;
          }
          private String dateFrom;
          private String dateTo;

          在Input頁面中,需要把onFormSubmit改一下:
          Object onFormSubmit() {
                  List<String> list = new ArrayList<String>();
                  output.setParamList(list);
                  return output;
          }

          其中,需要注意的是output中的onActivate方法,基參數(shù)的順序必須和List中放入的參數(shù)順序一致。


           

          posted @ 2010-02-06 12:36 云自無心水自閑 閱讀(3586) | 評論 (4)編輯 收藏

          在上一篇中我們研究了如何實現(xiàn)SpringSecurity中Jsp Tag的<security:authorize ifAllGranted="ROLE_SUPERVISOR">的功能。這一次我們一起研究一下如何實現(xiàn)在Tapestry5.1中添加一個Filter來對所有的操作進行權限的過濾控制。
          在SpringSecurity中,我們一般是在application-context.xml中,添加一個SpringSecurity的Filter,然后在另外一個xml中詳細配置如何根據(jù)Url的規(guī)則進行權限的控制。而Tapestry的哲學是盡量減少Xml中的配置(其IOC容器也基本上是借鑒Guice而不Spring的),所以我們也是在代碼中實現(xiàn)權限規(guī)則的控制。
          總體上來看,可以用兩種方式來實現(xiàn)url規(guī)則,一種是Request級別的Filter,一種是頁面組件級別的Filter,如果是Request級別的話,可以從Request對象中獲取Url路徑,這樣就與SpringSecurity基本一樣了。本文主要介紹頁面組件級別的Filter,從中我們也可以體會到Tapestry5.1中的IOC容器的強大和便利。

          這就是Filter的代碼,這個Filter必須實現(xiàn)ComponentRequestFilter接口。值得注意的是其構(gòu)造函數(shù)所需要用到的4個參數(shù),這4個參數(shù)都是Tapestry5本身自有的服務,所以我們什么也不用做,Tapestry5自動會將服務的實例注入進來,這就是Tapestry-IOC的威力。
          ComponentRequestFilter接口一共有4個方法需要實現(xiàn),具體代碼如下:

           1 public class RequiresLoginFilter implements ComponentRequestFilter {
           2 
           3     private final PageRenderLinkSource renderLinkSource;
           4 
           5     private final ComponentSource componentSource;
           6 
           7     private final Response response;
           8    
           9     private final ApplicationStateManager appStateManager;
          10    
          11     public RequiresLoginFilter(PageRenderLinkSource renderLinkSource,
          12             ComponentSource componentSource, Response response,
          13             ApplicationStateManager appStateManager
          14             ) {
          15         this.renderLinkSource = renderLinkSource;
          16         this.componentSource = componentSource;
          17         this.response = response;
          18         this.appStateManager = appStateManager;
          19     }
          20 
          21     public void handleComponentEvent(
          22             ComponentEventRequestParameters parameters,
          23             ComponentRequestHandler handler) throws IOException {
          24 
          25         if (dispatchedToLoginPage(parameters.getActivePageName())) {
          26             return;
          27         }
          28 
          29         handler.handleComponentEvent(parameters);
          30 
          31     }
          32 
          33     public void handlePageRender(PageRenderRequestParameters parameters,
          34             ComponentRequestHandler handler) throws IOException {
          35         if (dispatchedToLoginPage(parameters.getLogicalPageName())) {
          36             return;
          37         }
          38         handler.handlePageRender(parameters);
          39 
          40     }
          41 
          42     private boolean dispatchedToLoginPage(String pageName) {
          43         Component page = componentSource.getPage(pageName);
          44        
          45         if (page.getClass().isAnnotationPresent(RequiresLogin.class)) {
          46             if ( ! appStateManager.exists(Authentication.class)) {
          47                 redirect();
          48                 return true;
          49             }
          50             Authentication auth = appStateManager.get(Authentication.class);
          51             if ( auth == null ) {
          52                 redirect();
          53                 return true;
          54             }
          55            
          56              if ( ! auth.isLoggedIn()) {
          57                  redirect();
          58                  return true;
          59              }
          60 
          61             RequiresLogin requireLogin = page.getClass().getAnnotation(
          62                     RequiresLogin.class);
          63             String ifNotGranted = requireLogin.ifNotGranted();
          64             String ifAllGranted = requireLogin.ifAllGranted();
          65             String ifAnyGranted = requireLogin.ifAnyGranted();
          66             boolean permitted = auth.checkPermission(ifNotGranted, ifAllGranted, ifAnyGranted);
          67             if ( ! permitted ) {
          68                 return true;
          69             }
          70         }
          71 
          72         return false;
          73     }
          74    
          75     private void redirect() {
          76          Link link = renderLinkSource.createPageRenderLink("Logout");
          77        
          78          try {
          79              response.sendRedirect(link);
          80          } catch (Exception e) {
          81          }
          82     }
          83 
          84 }

          在ComponentRequestFilter中,我們無法使用@SessionState注解來直接注入Session中的變量,但是我們可以通過ApplicationStateManager來取得。

          現(xiàn)在我們需要把剛定義的Filter注冊到系統(tǒng)中,很簡單,只要在AppModule中添加以下函數(shù)就行了:

          1 public static void contributeComponentRequestHandler(
          2                 OrderedConfiguration<ComponentRequestFilter> configuration) {
          3         configuration.addInstance("RequiresLogin", RequiresLoginFilter.class);
          4 }
          5 
          從本例子中我們可以看到Tapesty Ioc容器使用的便利性,也認識到了Ioc容器在Tapestry體系中的重要性

          posted @ 2010-02-04 19:17 云自無心水自閑 閱讀(3230) | 評論 (1)編輯 收藏

          IBatis2中提供了3種DataSource的配置:JNDI, Apache DBCP, IBatis自帶的SimpleDataSource。但在IBatis3中只提供了兩種DataSource: UNPOOLED, POOLED。
          如果要實現(xiàn)自定義的DataSource,就需要通過擴展DataSourceFactory。本文就演示一下這個過程。
          準備工作:Connection Pool的選擇,通過搜索發(fā)現(xiàn)目前比較流行的免費數(shù)據(jù)庫連接池主要有3種:Apache DBCP, C3P0, Proxool。
          看了一下,Proxool的最新版本是0.9.1(2008-08-23), C3P0的最新版本是0.9.1.2(2007-05-21), DBCP最新版本是1.2.2(2007-04-04)
          好像這3個項目都已經(jīng)挺長時間沒有更新了。但是總體評價上C3P0無論從穩(wěn)定上還是效率上都要好一點。
          (具體這3個項目誰更優(yōu)秀,并不是本文的重點,本文主要是介紹一下如何在IBatis3中自定義數(shù)據(jù)源)
          大致步驟:
          1、實現(xiàn)org.apache.ibatis.datasource.DataSourceFactory接口,主要是2個方法
          a、public DataSource getDataSource() 如何具體地得到一個數(shù)據(jù)源
          b、public void setProperties(Properties properties) 如何設置數(shù)據(jù)源的參數(shù)屬性
          2、實現(xiàn)javax.sql.DataSource,這個就是提供給DataSourceFactory的實例
          3、在IBatis3中引用新加入的數(shù)據(jù)源

          1. 從代碼中可以看出,IBatis3與IBatis2不同,不再通過一個Configuration類來進行數(shù)據(jù)源屬性的設置,而是使用反射機制直接調(diào)用數(shù)據(jù)源的方法來設置參數(shù)。
          這就要求配置文件中的參數(shù)名稱必須與數(shù)據(jù)源類中的方法名匹配.
           1 public class C3p0DataSourceFactory implements DataSourceFactory {
           2 
           3     private DataSource dataSource;
           4 
           5     public C3p0DataSourceFactory() {
           6         dataSource = new C3p0DataSource();
           7     }
           8 
           9     public DataSource getDataSource() {
          10         return dataSource;
          11     }
          12 
          13     public void setProperties(Properties properties) {
          14         Properties driverProperties = new Properties();
          15         MetaObject metaDataSource = MetaObject.forObject(dataSource);
          16         for (Object key : properties.keySet()) {
          17             String propertyName = (String) key;
          18             if (propertyName.startsWith(DRIVER_PROPERTY_PREFIX)) {
          19                 String value = properties.getProperty(propertyName);
          20                 driverProperties.setProperty(propertyName
          21                         .substring(DRIVER_PROPERTY_PREFIX_LENGTH), value);
          22             } else if (metaDataSource.hasSetter(propertyName)) {
          23                 String value = (String) properties.get(propertyName);
          24                 Object convertedValue = convertValue(metaDataSource,
          25                         propertyName, value);
          26                 metaDataSource.setValue(propertyName, convertedValue);
          27             } else {
          28                 throw new DataSourceException("Unkown DataSource property: "
          29                         + propertyName);
          30             }
          31         }
          32         if (driverProperties.size() > 0) {
          33             metaDataSource.setValue("driverProperties", driverProperties);
          34         }
          35     }
          36 
          37     @SuppressWarnings("unchecked")
          38     private Object convertValue(MetaObject metaDataSource, String propertyName,
          39             String value) {
          40         Object convertedValue = value;
          41         Class targetType = metaDataSource.getSetterType(propertyName);
          42         if (targetType == Integer.class || targetType == int.class) {
          43             convertedValue = Integer.valueOf(value);
          44         } else if (targetType == Long.class || targetType == long.class) {
          45             convertedValue = Long.valueOf(value);
          46         } else if (targetType == Boolean.class || targetType == boolean.class) {
          47             convertedValue = Boolean.valueOf(value);
          48         }
          49         return convertedValue;
          50     }
          51 
          52     private static final String DRIVER_PROPERTY_PREFIX = "driver.";
          53     private static final int DRIVER_PROPERTY_PREFIX_LENGTH = DRIVER_PROPERTY_PREFIX
          54             .length();
          55 
          56 }
          57 

          2. 數(shù)據(jù)源類,其中的一堆setter就是用于設置屬性的。
           1 public class C3p0DataSource implements DataSource {
           2 
           3     private ComboPooledDataSource dataSource;
           4     public C3p0DataSource() {
           5         this.dataSource = new ComboPooledDataSource();
           6     }
           7     
           8     public Connection getConnection() throws SQLException {
           9         return dataSource.getConnection();
          10     }
          11 
          12     public Connection getConnection(String username, String password)
          13             throws SQLException {
          14         return dataSource.getConnection(username, password);
          15     }
          16 
          17     public PrintWriter getLogWriter() throws SQLException {
          18         return dataSource.getLogWriter();
          19     }
          20 
          21     public int getLoginTimeout() throws SQLException {
          22         return dataSource.getLoginTimeout();
          23     }
          24 
          25     public void setLogWriter(PrintWriter out) throws SQLException {
          26         dataSource.setLogWriter(out);
          27     }
          28 
          29     public void setLoginTimeout(int seconds) throws SQLException {
          30         dataSource.setLoginTimeout(seconds);
          31     }
          32     
          33     
          34     public synchronized void setDriver(String driver) {
          35         try {
          36             dataSource.setDriverClass(driver);
          37         } catch (Exception e) {
          38         }
          39     }
          40     
          41     public void setUrl(String url) {
          42         dataSource.setJdbcUrl(url);
          43     }
          44     
          45     public void setUsername(String username) {
          46           dataSource.setUser(username);
          47     }
          48 
          49     public void setPassword(String password) {
          50         dataSource.setPassword(password);
          51     }
          52     
          53     public void setInitialPoolSize(int initialPoolSize) {
          54         dataSource.setInitialPoolSize(initialPoolSize);
          55     }
          56     
          57     public void setMaxPoolSize(int maxPoolSize) {
          58         dataSource.setMaxPoolSize(maxPoolSize);
          59     }
          60       
          61     public void setMinPoolSize(int minPoolSize) {
          62         dataSource.setMinPoolSize(minPoolSize);
          63     }
          64     
          65     public void setPreferredTestQuery(String preferredTestQuery) {
          66         dataSource.setPreferredTestQuery(preferredTestQuery);
          67     }
          68     
          69     public void setPoolPingQuery(String poolPingQuery) {
          70         dataSource.setPreferredTestQuery(poolPingQuery);
          71     }
          72 }

          3. 在配置文件Configuration.xml中,可以先定義數(shù)據(jù)源的別稱,然后就象POOLED和UNPOOLED一樣使用別稱來引用數(shù)據(jù)源。
          <Configuration>
              ...
              <typeAlias>
                  <typeAlias type="com.test.datasource.C3p0DataSourceFactory" alias="C3P0"/>
              </typeAlias>
              <environments default="development">
                  <environment id="development">
                      <transactionManager type="JDBC"/>
                      <dataSource type="C3P0">
                          <property name="driver" value="${jdbc.driver}"/>
                          <property name="url" value="${jdbc.url}"/>
                          <property name="username" value="${jdbc.username}"/>
                          <property name="password" value="${jdbc.password}"/>
                          <property name="poolPingQuery" value="${pingquery}"/>           
                      </dataSource>
                  </environment>
              </environments>
              ...
          <Configuration>



          posted @ 2010-02-01 12:57 云自無心水自閑 閱讀(3921) | 評論 (2)編輯 收藏

          最近在使用tapestry5.1.0.5開發(fā)項目的時候,突然報錯:
          Exception in thread "main" java.lang.ClassFormatError: Invalid length 561 in LocalVariableTable in class file

          在網(wǎng)上搜索后,發(fā)現(xiàn)有人也有同樣的錯誤,解決方法有兩種:
          http://mail-archives.apache.org/mod_mbox/tapestry-users/200909.mbox/%3Cecd0e3310909040909id5275beld935fc60d54d490a@mail.gmail.com%3E
          其中一個人的錯誤原因是在其類路徑中有不同版本的javassists的jar文件。
          另一個的解決方法是使用eclipse自帶的jdk來編譯java類。
          而我自己仔細檢查了類路徑中的文件,并沒有重復的javassists,不過我覺得問題應該就在javassists上,
          因為這顯然是javassists在操作class文件時報的錯誤,
          我去網(wǎng)上搜索這方面的信息,發(fā)現(xiàn)有好幾個人都和我一樣在使用javassists3.11.0GA版本的時候,會出現(xiàn)這個錯誤。
          后來,我改用Tapestry5中自帶的javassists3.9.0GA后,問題消失了。
          這次經(jīng)驗教訓是并不是所有最新的東西都是最好的。合適的才是最好的。

          posted @ 2010-01-21 07:28 云自無心水自閑 閱讀(3684) | 評論 (0)編輯 收藏

          IBatis3的Beta8版本已經(jīng)發(fā)布了,在官方網(wǎng)站上聲稱目前的版本已經(jīng)非常穩(wěn)定,只有4個已知的問題,其中2個是非功能性的。作者宣稱,這樣的狀況使它對于近期發(fā)布GA版本充滿信心。
          那么IBatis3與IBatis2相比,究竟變化在哪里呢?
          最重要的變化是IBatis3中引入了接口綁定(Interface Binding)的概念。在IBatis2中,沒有應用Java5的泛型,所以需要大量使用強制類型轉(zhuǎn)換,比如:
          Employee employee = (Employee)sqlMapper.queryForList("getEmployee", 5);
          //...and...
          List employees = sqlMapper.queryForList("listAllEmployees");
          但是在IBatis3中,方法改變成:
          MapperFactory factory = someConfiguration.buildMapperFactory();
          EmployeeMapper employeeMapper = factory.getMapper (EmployeeMapper.class);
          Employee emp = empMapper.getEmployee(5);
          //...and...
          List<Employee> employees = empMapper.listAllEmployees();
          所以IBatis3至少需要使用Java5以上的版本。上面代碼中,EmployeeMapper是一個自定義的接口(注意,開發(fā)人員只需要定義一個接口,不需要提供具體的實現(xiàn))
          public interface EmployeeMapper {
            Employee getEmployee (int employeeId);
            List<Employee> listAllEmployees();
          }
          這樣就行了,IBatis會自動為你生成接口的具體實現(xiàn)。是不是感覺有點酷?

          posted @ 2010-01-15 20:49 云自無心水自閑 閱讀(2372) | 評論 (4)編輯 收藏

          僅列出標題
          共29頁: First 上一頁 7 8 9 10 11 12 13 14 15 下一頁 Last 
          主站蜘蛛池模板: 惠水县| 滁州市| 清徐县| 章丘市| 鞍山市| 西宁市| 朝阳县| 孟州市| 永清县| 仙游县| 佛冈县| 思南县| 神木县| 宁南县| 福海县| 秦安县| 永宁县| 松桃| 隆德县| 凤山市| 桑植县| 嘉禾县| 淮南市| 临猗县| 遵义县| 栾川县| 涞水县| 凯里市| 东辽县| 上林县| 建平县| 桃江县| 达日县| 沛县| 灵宝市| 万州区| 台江县| 芒康县| 同仁县| 叶城县| 芷江|