Fork me on GitHub

Example: JPA Picker (External Document Field Picker)

Configuring Field in Document Template (a.k.a 'namespace')

In a namespace bootstrap XML file, you should add a custom field like the following example (an example with SimpleJPQLExternalDocumentServiceFacade executing JPQL queries against external database):

<?xml version="1.0" encoding="UTF-8"?>
<sv:node sv:name="newsdocument" xmlns:sv="http://www.jcp.org/jcr/sv/1.0">
  <sv:property sv:name="jcr:primaryType" sv:type="Name">
    <sv:value>hipposysedit:templatetype</sv:value>
  </sv:property>

  <!-- SNIP -->

  <sv:node sv:name="editor:templates">
    <sv:property sv:name="jcr:primaryType" sv:type="Name">
      <sv:value>editor:templateset</sv:value>
    </sv:property>
    <sv:node sv:name="_default_">
      <sv:property sv:name="jcr:primaryType" sv:type="Name">
        <sv:value>frontend:plugincluster</sv:value>
      </sv:property>

      <!-- SNIP -->

      <!--
        You should add something like the following for each External Document Picker field.
        Most part will be used without modification except of the plugin parameters.
      -->

      <sv:node sv:name="informantextdocselector">
        <sv:property sv:name="jcr:primaryType" sv:type="Name">
          <sv:value>frontend:plugin</sv:value>
        </sv:property>
        <sv:property sv:name="caption" sv:type="String">
          <sv:value>Informant</sv:value>
        </sv:property>
        <sv:property sv:name="engine" sv:type="String">
          <sv:value>${engine}</sv:value>
        </sv:property>
        <sv:property sv:name="external.document.service.facade" sv:type="String">
          <sv:value>org.onehippo.forge.exdocpicker.demo.jpa.field.SimpleJPQLExternalDocumentServiceFacade</sv:value>
        </sv:property>
        <sv:property sv:name="initial.search.enabled" sv:type="Boolean">
          <sv:value>true</sv:value>
        </sv:property>
        <sv:property sv:name="jpql.external.docs.field.name" sv:type="String">
          <sv:value>exdocpickerbasedemo:informantids</sv:value>
        </sv:property>
        <sv:property sv:name="jpql.item.description.prop" sv:type="String">
          <sv:value>description</sv:value>
        </sv:property>
        <sv:property sv:name="jpql.item.iconlink.prop" sv:type="String">
          <sv:value>photo</sv:value>
        </sv:property>
        <sv:property sv:name="jpql.item.id.prop" sv:type="String">
          <sv:value>id</sv:value>
        </sv:property>
        <sv:property sv:name="jpql.item.id.type.prop" sv:type="String">
          <sv:value>long</sv:value>
        </sv:property>
        <sv:property sv:name="jpql.item.search.query" sv:type="String">
          <sv:value>SELECT i FROM Informant i WHERE i.id = :id</sv:value>
        </sv:property>
        <sv:property sv:name="jpql.item.search.query.param" sv:type="String">
          <sv:value>id</sv:value>
        </sv:property>
        <sv:property sv:name="jpql.item.title.prop" sv:type="String">
          <sv:value>name</sv:value>
        </sv:property>
        <sv:property sv:name="jpql.persistence.unit" sv:type="String">
          <sv:value>newsPU</sv:value>
        </sv:property>
        <sv:property sv:name="jpql.term.search.query" sv:type="String">
          <sv:value>SELECT i FROM Informant i</sv:value>
        </sv:property>
        <sv:property sv:name="jpql.term.search.query.param" sv:type="String">
          <sv:value/>
        </sv:property>
        <sv:property sv:name="mode" sv:type="String">
          <sv:value>${mode}</sv:value>
        </sv:property>
        <sv:property sv:name="plugin.class" sv:type="String">
          <sv:value>org.onehippo.forge.exdocpicker.impl.field.ExternalDocumentFieldSelectorPlugin</sv:value>
        </sv:property>
        <sv:property sv:name="selection.mode" sv:type="String">
          <sv:value>multiple</sv:value>
        </sv:property>
        <sv:property sv:name="wicket.id" sv:type="String">
          <sv:value>${cluster.id}.field</sv:value>
        </sv:property>
        <sv:property sv:name="wicket.model" sv:type="String">
          <sv:value>${wicket.model}</sv:value>
        </sv:property>
        <sv:node sv:name="cluster.options">
          <sv:property sv:name="jcr:primaryType" sv:type="Name">
            <sv:value>frontend:pluginconfig</sv:value>
          </sv:property>
        </sv:node>
      </sv:node>

      <!-- SNIP -->

    </sv:node>
  </sv:node>
</sv:node>
          

See the following for a full example in the demo project: https://github.com/bloomreach-forge/external-document-picker/tree/master/demo/bootstrap/configuration/src/main/resources/namespaces/exdocpickerbase-demo/newsdocument.xml

JPA/JPQL based ExternalDocumentServiceFacade implementation

See an example JPA/JPQL based ExternalDocumentServiceFacade implementation code here: https://github.com/bloomreach-forge/external-document-picker/tree/master/demo/cms/src/main/java/org/onehippo/forge/exdocpicker/demo/jpa/field/SimpleJPQLExternalDocumentServiceFacade.java

Plugin Parameters

You may configure the following plugin parameters in the field definition of your document template definition (a.k.a 'namespace').

Parameter name Description Example value(s) Default value(s)
caption Field caption, used as field label and dialog title. "Informant" "Related external documents"
external.document.service.facade org.onehippo.forge.exdocpicker.api.ExternalDocumentServiceFacade implementation class FQN. "org.onehippo.forge.exdocpicker.demo.jpa.field.SimpleJPQLExternalDocumentServiceFacade"
selection.mode External document selection mode. Either 'single' or 'multiple'. If this is 'single', then users can select only one external document item in the UI. Otherwise, users can select multiple external document items. "single" or
"multiple"
"multiple"
dialog.size The size of the picker popup dialog. "width=600,height=400" "width=835,height=650"
initial.search.enabled Flag whether the popup dialog box will search external documents initially when opening up. true false
initial.search.query Search query string or search term when the initial search is made in the dialog box when opening up if initial.search.enabled is set to true.

Note: it's up to the ExternalDocumentServiceFacade implementation to determine how to deal with the search query argument.
"*" ""
page.size The page size (item count per page) in the popup dialog. 10 5

Plugin Specific Parameters of SimpleJPQLExternalDocumentServiceFacade

The following parameters are set for the SimpleJPQLExternalDocumentServiceFacade implementation additionally.

Parameter name Description Example value(s) Default value(s)
jpql.external.docs.field.name The physical node property name to read from or store to when selection an external document. exdocpickerbasedemo:informantids
jpql.persistence.unit JPA persistence unit name defined in persistence-unit.xml newsPU
jpql.term.search.query JPQL full text search statement to find multiple external documents by a search term when user enters a search term and clicks on the search button in the picker dialog. SELECT i FROM Informant i
jpql.term.search.query.param If there is a named parameter in 'jpql.term.search.query' property, then you can specify the parameter name in this property.
For example, if 'jpql.term.search.query' is set to 'SELECT i FROM Informant i WHERE i.name = :name', then you can set this property to 'name'.
jpql.item.search.query JPQL search query statement to find single external document by a parameter such as ID. SELECT i FROM Informant i WHERE i.id = :id
jpql.item.search.query.param If there is a named parameter in 'jpql.item.search.query.param' property, then you can specify the parameter name in this property.
For example, if 'jpql.item.search.query.param' is set to 'SELECT i FROM Informant i WHERE i.id = :id', then you can set this property to 'id'.
id
jpql.item.id.prop The ID property name to retrieve after selecting a JPA POJO bean.
For example, if the JPQL query selects multiple Informant beans and user selects one from it, then the plugin will need to retrieve the ID property from the Informant bean instance. If this property is set to 'id' for instance, then the plugin will invoke Informant#getId() to retrieve the ID in the end.
id
jpql.item.id.type.prop The type of the ID property of the JPA POJO bean. It must be 'int', 'long', 'float', 'double' or 'String'. This type information is used for the parameter when executing the JPQL query configured by 'jpql.item.search.query' property. long
jpql.item.title.prop The title property name to display in the picker dialog after selecting a JPA POJO bean.
For example, if the JPQL query selects multiple Informant beans and user selects one from it, then the plugin will need to retrieve the title property from the Informant bean instance. If this property is set to 'name' for instance, then the plugin will invoke Informant#getName() to retrieve the title in the end.
name
jpql.item.description.prop The description property name to display in the picker dialog after selecting a JPA POJO bean.
For example, if the JPQL query selects multiple Informant beans and user selects one from it, then the plugin will need to retrieve the description property from the Informant bean instance. If this property is set to 'description' for instance, then the plugin will invoke Informant#getDescription() to retrieve the title in the end.
description
jpql.item.iconlink.prop The icon URL link property name to display in the picker dialog after selecting a JPA POJO bean.
For example, if the JPQL query selects multiple Informant beans and user selects one from it, then the plugin will need to retrieve the icon URL link property from the Informant bean instance. If this property is set to 'photo' for instance, then the plugin will invoke Informant#getPhoto() to retrieve the icon URL link in the end.
photo