本站首页    管理页面    写新日志    退出


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告
 本博客在此声明所有文章均为转摘,只做资料收集使用。

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:1304
评论数量:2242
留言数量:5
访问次数:7593774
建立时间:2006年5月29日




[Java Open Source]Integrate Compass, Appfuse, DisplayTag Tutorial Part 5
软件技术

lhwork 发表于 2007/1/23 9:01:53

The goal of this tutorial is to use DiaplayTag to help layout easier.   Before we start, we have to understand some features of Compass and DisplayTag.   In CompassAction's ActionForward "list" method, we have a request parameter named "page".   The page value is used in Method performSearch in BaseCompassAction.java to determine where should the hits "detach" from.   In BaseCompassAction.java, we have a Integer named "pageSize".   The pageSize value is used in Method performSearch to determine the size that the hits should be "detach";   In other words, when we get a searchResults return, it is a segment of all hits.   For example, the hit length is 10000, we get 00010 ~ 00019 with page=1 and pageSize=10.   It's good news.   But for DisplayTag layout, it needs a list with a really length = 10000 to properly display the results with paging feature.   Another issue is DisplayTag's first page index is "1" instead of "0".   That means we need to do something to "cheat" DisplayTag ^^   The way is we create a list with length = 10000, but just set objects from 00010 ~ 00019.   Then set it to request scope for DisplayTag layout.   The original idea is from  Xexex's blog, a post named "Pageable DisplayTag with Hibernate".    All codes could be download here.   I remove lib, extra, docs folders to reduce size.   Step 1. Prepare proper list for DisplayTag   1. Edit "CompassSearchResults.java" and append below codes   ------ start here ------      private int totalCount;        public int getTotalCount() {  return totalCount; }  public void setTotalCount(int totalCount) {  this.totalCount = totalCount; }  public CompassSearchResults(CompassHit[] hits, long searchTime, int totalCount) {        this.hits = hits;        this.searchTime = searchTime;        this.totalCount = totalCount;    }    ------ End here ------ Default CompassSearchResults does not keep the length of the hits before detach. But we need the length. Here we add a Constructor to keep totalCount value. We will use it to determine the "lengh" of list that we have to create to cheat DisplayTag. 2. Edit Method performSearch in BaseCompassAction.java   Mark up this line : CompassSearchResults searchResults = new CompassSearchResults(detachedHits.getHits(), time);   Add this line : CompassSearchResults searchResults = new CompassSearchResults(detachedHits.getHits(), time, hits.length());    3. Create class "CompassPageList.java" under src/web ... /util/ and add below codes   ------ start here ------   package org.myapp.webapp.util; import java.util.ArrayList;import java.util.Iterator;import java.util.List; import org.compass.core.CompassHit; public class CompassPageList {  private List cachedList; private int pageNo; private int pageSize; private int totalSize;  public CompassPageList(int pageSize, int totalSize)  {  this.pageSize = pageSize;  this.totalSize = totalSize;    //  initialize full list with null;  cachedList = new ArrayList(totalSize);  for (int i = 0; i < totalSize; i++)   {   cachedList.add(null);  }//for }  public void loadPage(final int pageNo,CompassHit[] result) {  // check cache has data:  if (pageIsCached(pageNo))   {   return;  }    int index = getPageStartRow(pageNo);    for(int i=0; i<result.length; i++){      cachedList.set(index, result[i].getData());      index ++;     }   }  private int getPageEndRow(int pageNo)  {  return Math.min(pageNo * pageSize, totalSize); } private int getPageStartRow(int pageNo)  {  return (pageNo - 1) * pageSize; }  private boolean pageIsCached(final int pageNo)  {  boolean pageIsCached = true;  for (int i = getPageStartRow(pageNo);i < getPageEndRow(pageNo) && pageIsCached; i++)   {   if (cachedList.get(i) == null)    {    pageIsCached = false;   }  }    return pageIsCached; } public Object get(int index)  {  return cachedList.get(index); } public boolean isEmpty()  {  return cachedList.isEmpty(); } public Iterator iterator()  {  return cachedList.iterator(); } public int size()  {   return cachedList.size(); } public int getPageSize()  {   return pageSize; }  public List list() {    return cachedList; }}   ------ End here ------     4. Add new Method named "nextPage" in BaseCompassAction and add below codes   ------ start here ------      protected int nextPage(HttpServletRequest request){        Enumeration names = request.getParameterNames();   int pageNo = 1;   while (names.hasMoreElements())    {    String parameter = (String) names.nextElement();    if (parameter.matches("d-[0-9]+-p"))     {      pageNo = Integer.parseInt(request.getParameter(parameter));      break;    }   }    return pageNo; } ------ End here ------  Why we need this method? ^^ DisplayTag determines what page now the user requests to visit by a special request parameter. For example, when user clicks page 3 link , "d-12345-p=3" added as parameter and send back to server Here "12345" is random. So, by parsing "d-12345-p=3", we can know what the page the user now request. This help us identify what page the user clicks.  Remember that DisplayTag's first page index is 1. ^^ 5. Edit "CompassAction.java"   Here we modify Method "list", copy and overwrite with below codes  ------ start here ------     public ActionForward list(ActionMapping mapping, ActionForm form,              HttpServletRequest request,              HttpServletResponse response)  throws Exception {    System.out.println("Enter list method");    String query = request.getParameter("query");  //String pageStr = request.getParameter("page");    //Integer page = Integer.parseInt(pageStr);    int curPage = nextPage(request);    final CompassSearchCommand searchCommand = new CompassSearchCommand();    int searchCommandPage = curPage - 1;    searchCommand.setPage(searchCommandPage);  searchCommand.setQuery(query);          if (!StringUtils.hasText(searchCommand.getQuery())) {            return mapping.findForward("list");        }                Compass compass = (Compass) getBean("compass");                CompassSearchResults searchResults;                searchResults = (CompassSearchResults) new CompassTemplate(compass).execute(                CompassTransaction.TransactionIsolation.READ_ONLY_READ_COMMITTED, new CompassCallback() {            public Object doInCompass(CompassSession session) throws CompassException {                return performSearch(searchCommand, session);            }        });          CompassHit[] cha = searchResults.getHits();                CompassPageList list = new CompassPageList(Constants.PAGE_SIZE, searchResults.getTotalCount());    list.loadPage(curPage, cha);          request.setAttribute("CompassHits", list.list());          return mapping.findForward("list"); } ------ End here ------  We mark up : String pageStr = request.getParameter("page"); and Integer page = Integer.parseInt(pageStr);  Add : int curPage = nextPage(request);  The "curPage" means the page number the user reauest.  The "searchCommandPage" means the page number we want compass to detach from.  A CompassPageList is created for DisplayTag use.  6. Edit "CompassListActionTest.java", copy and overwrite with below codes.   ------ start here ------  package org.myapp.webapp.action; import java.util.Date;import java.util.Iterator;import java.util.List;import java.util.Random; import org.myapp.service.LookupManager;import org.compass.core.CompassHit;import org.myapp.model.Chapter;import org.myapp.model.Document; public class CompassListActionTest extends BaseStrutsTestCase {     public CompassListActionTest(String name) {        super(name);    }     protected void setUp() throws Exception {        super.setUp();        getMockRequest().setUserRole("admin");    }        public void testAddData(){          Random rnd = new Random();          LookupManager mgr = (LookupManager) ctx.getBean("lookupManager");          for(int i=0; i<2; i++){             Document document = new Document();            document.setKeyWords("keyword"+ rnd.nextInt());      document.setTitle("title"+ rnd.nextInt());      //document.setPublishDate(new Date());      document.setVersion(1);            for(int j=0; j<10; j++){              Chapter chapter = new Chapter();              chapter.setContent("content"+ rnd.nextInt());       chapter.setTitle("title"+ rnd.nextInt());              mgr.saveObject(chapter);              document.getChapters().add(chapter);      }           mgr.saveObject(document);     }         }        /*     * jack        Contain the term jack in the default search field     * jack london (jack or london)  Contains the term jack or london, or both, in the default search field     * +jack +london (jack and london) Contains both jack and london in the default search field     * name:jack      Contains the term jack in the name property (meta-data)     *      * name:jack -city:london (name:jack and not city:london) Have jack in the name property and don't have london in the city property     *      * name:"jack london"    Contains the exact phrase jack london in the name property     * name:"jack london"~5    Contain the term jack and london within five positions of one another     * jack*       Contain terms that begin with jack     * jack~       Contains terms that are close to the word jack     *      * birthday:[1870/01/01 TO 1920/01/01] Have the birthday values between the specified values. Note that it is a lexicography range     */        public void testList_1() throws Exception {             setRequestPathInfo("/compass");        addRequestParameter("method", "list");        addRequestParameter("query", "title*");        addRequestParameter("d-12345-p", "2");        actionPerform();         verifyForward("list");        verifyNoActionErrors();                List list = (List)request.getAttribute("CompassHits");                Iterator it = list.iterator();                while(it.hasNext()){                  Object o = it.next();         System.out.println("o : "+ o);                 }            }     public void testList_2() throws Exception {        setRequestPathInfo("/compass");        addRequestParameter("method", "list");        addRequestParameter("query", "title:title01");        addRequestParameter("d-12345-p", "1");        actionPerform();         verifyForward("list");        verifyNoActionErrors();                List list = (List)request.getAttribute("CompassHits");                Iterator it = list.iterator();                while(it.hasNext()){                  Object o = it.next();         System.out.println("o : "+ o);                 }    }        public void testList_3() throws Exception {        setRequestPathInfo("/compass");        addRequestParameter("method", "list");        addRequestParameter("query", "title001");        addRequestParameter("d-12345-p", "1");        actionPerform();         verifyForward("list");        verifyNoActionErrors();                List list = (List)request.getAttribute("CompassHits");                Iterator it = list.iterator();                while(it.hasNext()){                  Object o = it.next();         System.out.println("o : "+ o);                 }    }    }   ------ End here ------   Note:   In "testAddData", I create documents and chapters as preload data for test.   You will find that why I save chapter and document independently?   Here I have synchronous problem in Session.   If someone knows how to make compasee and hibernate synchronous correctly. Please let me know.   7. Run "ant create-lucene-index" and "ant CompassListActionTest" to see reults.   You will find that a list created to cheat DisplayTag  Note:   Since ant task test-web depends on db-load, every time you run test, you have default data in db.  But the index is not cleared.   Watch out this ^^  Run ant task create-lucene-index if you need it.   Step 2. Deploy your application   1. Create jsp named "compassList.jsp" under \web\pages and add codes below    ------ start here ------  <%@ include file="/common/taglibs.jsp"%> <display:table name="CompassHits" id="CompassHits" pagesize="10" class="table" requestURI="">  <display:column property="id" title="ID" />  <display:column property="class.simpleName" title="Class Name"/>   <display:column property="title" /> </display:table>    ------ End here ------   2. Edit "build.xml" overwrite task "package-service" with below and script   ------ start here ------    <target name="package-service" depends="compile-service">        <mkdir dir="${build.dir}/service/classes/META-INF"/>        <copy tofile="${build.dir}/service/classes/META-INF/applicationContext-service.xml">            <fileset dir="src/service" includes="**/*-service.xml"/>        </copy>        <copy todir="${build.dir}/service/classes">            <fileset dir="src/service" includes="**/*.cpm.xml"/>        </copy>        <jar destfile="${dist.dir}/${webapp.name}-service.jar">            <manifest>                <attribute name="Class-Path"                    value="${webapp.name}-dao.jar ${webapp.name}-service.jar"/>            </manifest>            <fileset dir="${build.dir}/service/classes" includes="**/*.class"/>            <fileset dir="${build.dir}/service/classes" includes="**/*.cpm.xml"/>            <metainf dir="${build.dir}/service/classes/META-INF"/>        </jar>    </target>   ------ End here ------    Here I copy cpm file to classes and jar    3. Deploy and run it  Browse to http://localhost:8080/myapp/compass.html?query=title*&d-5397244-p=1&method=list  And see results ^^  You could check the screen here  Summary   In the source code of "Document.java", I mark up attribute "publishDate" annotaion.  The situation is the test case runs well, but always failed in container.  Since I always got parse date failed and can not find ways what's wrong = =.   If someone could help me fix it, I will be very appreciate. 


阅读全文(8196) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.305 second(s), page refreshed 144765696 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号