Page 1 of 1

SOLR Indexing via Admin Panel using Standalone SOLR server

Posted: Thu Aug 13, 2015 10:56 am
by rudy
Broadleaf is configured for using embedded SOLR plugin and is scheduled to index the data on server startup and then after every hour. I wanted to make this process manual via Admin Panel.

Therefore, i did the following steps.

Configure Standalone SOLR server in Broadleaf 4.0

1. Setup standalone SOLR server at port 8983 [which is default for SOLR].
Create two cores viz. "primary" and "reindex". You can use any other name of your choice.

2. In common.properties in the site module, comment the following lines. This will disable the embedded SOLR server.

Code: Select all

solr.source.primary=solrEmbedded
solr.source.reindex=solrEmbedded
solr.source.admin=solrEmbedded


Also, the following lines represent the time for starting auto-indexing.
You can choose to comment these lines, if you want to get rid of auto-indexing altogether.

Code: Select all

solr.index.start.delay=5000
solr.index.repeat.interval=3600000


solr.index.start.delay=5000 refers to the time (in milliseconds) after which the indexing will start on server-start.
5000 milliseconds = 5 seconds
solr.index.repeat.interval=3600000 refers to the time (in milliseconds) after which the indexing will restart, while the server is running.
3600000 milliseconds = 1 hour x 60 minutes x 60 seconds x 1000 milliseconds

3. Next, since the SOLR server is to be accessed in admin module, the configuration should reside in core module.
in common-shared.properties, add the following lines at the bottom:-

Code: Select all

solr.source.primary=solrServer
solr.source.reindex=solrReindexServer
solr.source.admin=solrAdminServer
solr.url.primary=http://localhost:8983/solr/primary
solr.url.reindex=http://localhost:8983/solr/reindex
solr.url.admin=http://localhost:8983/solr


4. Open applicationContext.xml inside "site" module.
Comment the following lines to disable embedded SOLR plugin.

Code: Select all

<!--
<bean id="solrEmbedded" class="java.lang.String">
        <constructor-arg value="solrhome"/>
</bean>
-->


If you wish to disable auto-indexing completely, comment below code completely in same file. If not, skip this part.

Code: Select all

<bean id="rebuildIndexJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="blSearchService" />
        <property name="targetMethod" value="rebuildIndex" />
    </bean>
    <bean id="rebuildIndexTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="rebuildIndexJobDetail" />
        <property name="startDelay" value="${solr.index.start.delay}" />
        <property name="repeatInterval" value="${solr.index.repeat.interval}" />
    </bean>
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="rebuildIndexTrigger" />
                <!--<ref bean="purgeCartTrigger" /> -->
                <!--<ref bean="purgeCustomerTrigger" /> -->
           </list>
        </property>
    </bean>


5. Next, in applicationContext.xml in core module, add the following lines.
This will enable standalone SOLR server and the URLs will be derived from properties in file common-shared.properties defined above.

Code: Select all

<bean id="solrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
             <constructor-arg value="${solr.url.primary}"/>
    </bean>
    <bean id="solrReindexServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
           <constructor-arg value="${solr.url.reindex}"/>
    </bean>
    <bean id="solrAdminServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
          <constructor-arg value="${solr.url.admin}"/>
    </bean>
       
    <bean id="blSearchService" class="com.medicodeal.core.search.service.solr.MDSolrSearchServiceImpl">
        <constructor-arg name="solrServer" ref="${solr.source.primary}" />
        <constructor-arg name="reindexServer" ref="${solr.source.reindex}" />
        <constructor-arg name="adminServer" ref="${solr.source.admin}" />
    </bean>


Now, broadleaf is configured to use standalone SOLR server.
NOTE: If you have made any changes to original schema.xml or solrConfig.xml, make sure you copy(and replace) the files into SOLR cores you created.
These files will be at the location<solr_installation_path>/server/solr/<core_name>/conf
In this example, there are two cores with namesprimary and reindex

Create new component for INDEXING

1. Inside the admin module, create a new controller to invoke the index on a URL hit.
In this example, we are mapping /indexData URL to start indexing the data.
After the data is indexed, it redirects to a URL.

Code: Select all

@Controller
public class AdminIndexingInvoker extends BroadleafAbstractController{
   
    @Resource(name = "blSolrIndexService")
    protected SolrIndexService solrIndexService;
      
   @RequestMapping(value = "/indexData", method = RequestMethod.GET)
   protected String invokeIndexing(Model model)throws IOException, ServiceException {
      boolean success = true;
      try {
         solrIndexService.rebuildIndex();
      } catch (Exception e) {
         LOG.debug(e);
         model.addAttribute("msg",e.toString());
         success = false;
      } finally {
         model.addAttribute("success",success);
      }
      return "redirect:/search/indexing";      
   }
}


New section in admin panel for INDEXING

1. Create new module in admin panel viz. "Search and Indexing", followed by a section inside of it named "Indexing".
Run following SQL queries:-

Code: Select all

--###################################
--CREATE NEW MODULE FOR "SEARCH"
--###################################

INSERT INTO BLC_ADMIN_MODULE (ADMIN_MODULE_ID, NAME, MODULE_KEY, ICON, DISPLAY_ORDER)
VALUES (9000, 'Search and Indexing','Search and Indexing', 'icon-file', 800);

--##################
--INDEXING SECTION
--##################

--## INDEXING SECTION ###
INSERT INTO BLC_ADMIN_SECTION (ADMIN_SECTION_ID, DISPLAY_ORDER, ADMIN_MODULE_ID, NAME, SECTION_KEY, URL, CEILING_ENTITY)
VALUES (9100, 1, 9000, 'Indexing', 'Indexing', '/search/indexing', null);

--## FRIENDLY PERMISSIONS ##
INSERT INTO BLC_ADMIN_PERMISSION (ADMIN_PERMISSION_ID, DESCRIPTION, NAME, PERMISSION_TYPE, IS_FRIENDLY)
VALUES (9001,'Kick Indexing','INDEXING_KICKER', 'ALL', '1');

--## MAP PERMISSION TO ADMIN ##
INSERT INTO BLC_ADMIN_ROLE_PERMISSION_XREF (ADMIN_ROLE_ID, ADMIN_PERMISSION_ID)
VALUES (-1,9001);

--## MAP SECTION TO PERMISSION ##
INSERT INTO BLC_ADMIN_SEC_PERM_XREF (ADMIN_SECTION_ID, ADMIN_PERMISSION_ID) VALUES (9100,9001);


2. Create new controller in admin module, to render the section "Indexing".
We have set the URL in the second query as /search/indexing

Code: Select all

@Controller("mdAdminSearchConfigurationController")
@Secured("PERMISSION_OTHER_DEFAULT")
public class AdminSearchConfigurationController extends AdminAbstractController {

   protected static final String SECTION_KEY_INDEXING = "search/indexing";
   
   @RequestMapping(value = "/search/indexing", method = RequestMethod.GET)
    public String getIndexing(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
        model.addAttribute("viewType", "indexing");
        setModelAttributes(model, SECTION_KEY_INDEXING);
        return "modules/defaultContainer";
    }
}


In above class the model being returned is "modules/defaultContainer".
This is already present in broadleaf.

Inside this container, we need to display some link/button to start indexing.
The first line inside getIndexing() method, sets the viewType as indexing.
As a part of defaultContainer, we need to supply this parameter (viewType).
Broadleaf expects an HTML corresponding to the value of viewType attribute in the views folder inside the web-application's template folder.

3. Lastly, we create "indexing.html", and provide a button to start indexing.
The button hits the URL /indexData of the controller AdminIndexingInvoker.
This starts the indexing, and returns back to the admin panel's page, with the status if indexing is successful or not.
indexing.html is below

Code: Select all

<div class="row">
    <div class="five columns" style="padding-top:17px;">
        <ul class="button-group">
            <li>
               Index Full Data: <a th:href="@{/indexData}" class="button small radius dark add-main-entity" th:inline="text">START INDEXING</a>
               <div th:unless="${#strings.isEmpty(param.success)}">
                  <span th:if="*{param.success[0]}" th:inline="text" style="color:green">
                     <b>Indexing Successful!!</b>
                  </span>
                  <span th:if="*{not param.success[0]}" th:inline="text" style="color:red">
                     <b>Indexing Failed due to:</b><br />
                     [[${param.msg[0]}]]
                  </span>
               </div>
            </li>
        </ul>
    </div>
</div>


This is pretty much it, and now you can kick your indexing from admin panel.
Also, please take a note, if you do not comment the scheduled run from common.properties and applicationContext.xml, the indexing will run as it used to.

Cheers,
Rudy