Few months ago I was developing a project on top of JBoss Portal. Unfortunately, JBoss Portal 2.7.x is a nice Portlet Container but a crappy CMS/Search engine -even when it is supported on Apache’s JackRabbit. However, I was forced to develop a search portlet. It wasn’t easy, and you will probably find that it is not a perfect solution. However I really hope you find this Search Portlet really useful.
SearchPortlet.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | package portal.portlets; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.GenericPortlet; import javax.portlet.PortletConfig; import javax.portlet.PortletException; import javax.portlet.PortletRequestDispatcher; import javax.portlet.PortletSecurityException; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.UnavailableException; import javax.portlet.WindowState; import org.apache.log4j.Logger; import org.jboss.portal.cms.CMS; import org.jboss.portal.cms.CMSException; import org.jboss.portal.cms.Command; import org.jboss.portal.cms.model.File; import org.jboss.portal.core.cms.ui.CMSPortlet; import org.jboss.portal.search.FederatedQuery; import org.jboss.portal.search.QueryConversionException; import org.jboss.portal.search.federation.SearchFederation; import org.jboss.portal.search.impl.jcr.JCRQuery; import org.jboss.portal.search.impl.jcr.JCRQueryConverter; public class SearchPortlet extends CMSPortlet { private static Logger log = Logger.getLogger(SearchPortlet.class); private SearchFederation SearchService; private CMS CMSService; public void init(PortletConfig config) throws PortletException { super.init(config); } public void destroy() { super.destroy(); } /* * (non-Javadoc) * * @see javax.portlet.Portlet#init() */ @Override public void init() throws PortletException { this.SearchService = (SearchFederation) getPortletContext().getAttribute("SearchFederationService"); this.CMSService = (CMS) getPortletContext().getAttribute("CMS"); if (this.SearchService == null) { throw new PortletException("Unable to start search service"); } if (this.CMSService == null) { throw new PortletException("CMS services not available"); } super.init(); } /* * (non-Javadoc) * * @see javax.portlet.GenericPortlet#doView(javax.portlet.RenderRequest, * javax.portlet.RenderResponse) */ @Override protected void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException, UnavailableException { String portalInstance = request.getWindowID().substring(0, request.getWindowID().indexOf('/', 1)); PortletRequestDispatcher prd = null; String operation = (String) request.getParameter("op"); if (operation != null && operation.equals("search")) { String queryString = (String) request.getParameter("query"); if (queryString != null && queryString.length() > 0) { request.setAttribute("files", this.getFiles(queryString, portalInstance)); prd = this.getPortletContext().getRequestDispatcher("/WEB-INF/jsp/results.jsp"); } else { prd = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/search.jsp"); } prd.include(request, response); } else if (operation != null && operation.equals("display")) { super.doView(request, response); } else { prd = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/search.jsp"); prd.include(request, response); } } /* * (non-Javadoc) * * @see javax.portlet.Portlet#processAction(javax.portlet.ActionRequest, * javax.portlet.ActionResponse) */ @Override public void processAction(ActionRequest request, ActionResponse response) throws PortletException, PortletSecurityException, IOException { String profile; String operation = (String) request.getParameter("op"); if (operation != null && operation.length() > 0) { if (operation.equals("ask")) { response.setWindowState(WindowState.NORMAL); } else { response.setWindowState(WindowState.MAXIMIZED); } response.setRenderParameter("op", operation); } else { response.setRenderParameter("op", "ask"); response.setWindowState(WindowState.NORMAL); } if (operation.equals("search")) { String queryString = (String) request.getParameter("query"); if (queryString != null && queryString.length() > 0) { response.setRenderParameter("query", queryString); } } } private List getFiles(String queryString, String portal) { List files = null; List filteredFiles = new ArrayList(); if (queryString != null && queryString.length() > 0) { FederatedQuery query = new FederatedQuery(queryString); JCRQueryConverter converter = new JCRQueryConverter(); try { Command searchCommand = CMSService.getCommandFactory().createSearchCommand((JCRQuery) converter.convert(query)); files = (List) CMSService.execute(searchCommand); // You can filter files if needed by reviewing its path under the CMS // structure, by name, or any other criteria that fits your needs. } catch (CMSException e) { log.error("CMS Error", e); } catch (QueryConversionException e) { log.warn("Conversion Error", e); } } return files; } } |
I used two JSP pages to support this portlet.
- search.jsp – Search form – the standard portlet view
- results.jsp – Results list page – appears with the portlet MAXIMIZED and displays CMS files that matches the criteria
search.jsp – (WP-Syntax does not support JSP)
1 2 3 4 5 6 7 8 | <h2>Search</h2> <form action="<%=contactActionURL%>" method="POST"> <fieldset style="border: none;"> <input name="op" type="hidden" value="search" /> <input name="query" type="text" /> <input type="submit" value="Search" /> </fieldset> </form> |
results.jsp – (WP-Syntax does not support JSP)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <%@ page import="org.jboss.portal.cms.model.File"%> <%@ page import="java.util.List"%> <%@ page language="java" extends="org.jboss.portal.core.servlet.jsp.PortalJsp"%> <%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%> <% List<File> files = (List<File>) request.getAttribute("files"); if (files != null && files.size() > 0) { %> <h1>RESULTADOS DE BÚQUEDA</h1> <% for (int i = 0; i < files.size(); i++) { File file = files.get(i); %> <h2><%= file.getName() %></h2> <p><% if (file.getDescription() != null && file.getDescription().length() > 0) { %><%= file.getDescription() %><% } %><a href="<portlet:actionURL><portlet:param name="op" value="display" /><portlet:param name="file" value="<%= file.getBasePath() %>" /></portlet:actionURL>">Ver más...</a></p> <hr /> <% } %> <% } else { %> <h1>NO HAY RESULTADOS</h1> <% } %> <p align="center"><a href="<portlet:actionURL><portlet:param name="op" value="ask" /></portlet:actionURL>">Volver</a></p> |
Include the following lines on your jboss-portlet.xml file.
1 2 3 4 5 6 7 8 9 10 11 | <service> <service-name>CMS</service-name> <service-class>org.jboss.portal.cms.CMS</service-class> <service-ref>:service=CMS</service-ref> </service> <service> <service-name>SearchFederationService</service-name> <service-class>org.jboss.portal.search.federation.SearchFederation</service-class> <service-ref>:service=SearchFederationService</service-ref> </service> |
And finally add the following lines on your portlet.xml file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <portlet> <description>DESC</description> <portlet-name>SearchPortlet</portlet-name> <display-name>NAME</display-name> <portlet-class>portal.portlets.SearchPortlet</portlet-class> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports> <resource-bundle>Resource</resource-bundle> <portlet-info> <title>SEARCH</title> </portlet-info> <portlet-preferences> <preference> <name>indexpage</name> <value>/default/index.html</value> </preference> <preference> <name>setBrowserTitle</name> <value>false</value> </preference> </portlet-preferences> </portlet> <filter> <filter-name>JBoss Portlet Filter</filter-name> <filter-class>org.jboss.portlet.filter.JBossPortletFilter</filter-class> <lifecycle>ACTION_PHASE</lifecycle> <lifecycle>RENDER_PHASE</lifecycle> </filter> <filter-mapping> <filter-name>JBoss Portlet Filter</filter-name> <portlet-name>SearchPortlet</portlet-name> </filter-mapping> |