Announcement: You can find the guides for Commerce 7.5 and later on the new Elastic Path Documentation site. The Developer Center continues to support Commerce 6.13.0 through 7.4.1.Visit new site

A Closer Look at the Core Lookup Resource

A Closer Look at the Core Lookup Resource

In this section, we explore how to make a connection between a resource and the Elastic Path Core to get a user's email address. Normally, you make a connection to the Core when you want data not readily available in other resources.

The Email DTO

Cortex API uses the Data Transfer Object (DTO) pattern to transfer information between the resources and the core. See Domain Interfacing with the Elastic Path Core for more information on DTOs.

The DTO for the CoreLookup resource is below:

               <html><body>
<pre class="j-path">rest-resource-corelookup<span class="j-pathsep">/</span>src<span class="j-pathsep">/</span>main<span class="j-pathsep">/</span>java<span class="j-pathsep">/</span>com<span class="j-pathsep">/</span>extension<span class="j-pathsep">/</span>rest<span class="j-pathsep">/</span>core<span class="j-pathsep">/</span>command<span class="j-pathsep">/</span>dto<span class="j-pathsep">/</span>EmailDto.java</pre>
<pre class="java"><span class="j-key">package </span>com.extension.rest.core.command.dto;

<span class="j-key">import </span>java.io.Serializable;

<span class="j-jdoc">/**
 * DTO for an Email. Despite the presence of only one field, there could potentially be many fields
 * and hence it is good programming practice to use both a DTO and its assembler when retrieving
 * information from core.
 */
</span><span class="j-key">public class </span>EmailDto <span class="j-key">implements </span>Serializable <span class="j-sym">{

  </span><span class="j-jdoc">/**
   * Serial UID.
   */
  </span><span class="j-key">private static final </span><span class="j-typ">long </span>serialVersionUID = <span class="j-num">1L</span>;

  <span class="j-key">private </span>String email;

  <span class="j-key">public </span>String getEmail<span class="j-sym">() {
    </span><span class="j-key">return </span>email;
  <span class="j-sym">}

  </span><span class="j-jdoc">/**
   * Gets the email.
   *
   * </span><span class="j-jdoc-key">@param </span><span class="j-jdoc">email the email
   * </span><span class="j-jdoc-key">@return </span><span class="j-jdoc">this instance
   */
  </span><span class="j-key">public </span>EmailDto setEmail<span class="j-sym">(</span><span class="j-key">final </span>String email<span class="j-sym">) {
    </span><span class="j-key">this</span>.email = email;
    <span class="j-key">return this</span>;
  <span class="j-sym">}
}</span></pre>
</body></html>
            

The EmailDTO has an accompanying assembler that creates DTO instances:

               <html><body>
<pre class="j-path">rest-resource-corelookup<span class="j-pathsep">/</span>src<span class="j-pathsep">/</span>main<span class="j-pathsep">/</span>java<span class="j-pathsep">/</span>com<span class="j-pathsep">/</span>extension<span class="j-pathsep">/</span>rest<span class="j-pathsep">/</span>core<span class="j-pathsep">/</span>command<span class="j-pathsep">/</span>dto<span class="j-pathsep">/</span>assembler<span class="j-pathsep">/</span>EmailDtoAssembler.java</pre>
<pre class="java"><span class="j-key">package </span>com.extension.rest.core.command.dto.assembler;

<span class="j-key">import </span>com.elasticpath.domain.customer.Customer;
<span class="j-key">import </span>com.extension.rest.core.command.dto.EmailDto;

<span class="j-jdoc">/**
 *
 * An assembler to create an </span><span class="j-jdoc-link">{@link EmailDto}</span><span class="j-jdoc">.
 */
</span><span class="j-key">public final class </span>EmailDtoAssembler <span class="j-sym">{

  </span><span class="j-key">private </span>EmailDtoAssembler<span class="j-sym">() {
    </span><span class="j-cmt">//static class
  </span><span class="j-sym">}

  </span><span class="j-jdoc">/**
   * Assembles an </span><span class="j-jdoc-link">{@link EmailDto} </span><span class="j-jdoc">from a </span><span class="j-jdoc-link">{@link Customer}</span><span class="j-jdoc">.
   *
   * </span><span class="j-jdoc-key">@param </span><span class="j-jdoc">customer the customer
   * </span><span class="j-jdoc-key">@return </span><span class="j-jdoc">an assembled </span><span class="j-jdoc-link">{@link EmailDto}
   </span><span class="j-jdoc">*/
  </span><span class="j-key">public static </span>EmailDto assembleEmailDto<span class="j-sym">(</span><span class="j-key">final </span>Customer customer<span class="j-sym">) {
    </span>EmailDto emailDto = createEmailDto<span class="j-sym">()</span>;

    emailDto.setEmail<span class="j-sym">(</span>customer.getEmail<span class="j-sym">())</span>;
    <span class="j-key">return </span>emailDto;
  <span class="j-sym">}

  </span><span class="j-jdoc">/**
   * Creates a new </span><span class="j-jdoc-link">{@link EmailDto}</span><span class="j-jdoc">.
   *
   * </span><span class="j-jdoc-key">@return </span><span class="j-jdoc">new email dto
   */
  </span><span class="j-key">protected static </span>EmailDto createEmailDto<span class="j-sym">() {
    </span><span class="j-key">return new </span>EmailDto<span class="j-sym">()</span>;
  <span class="j-sym">}
}</span></pre>
</body></html>
            

As you can see, the assembler interacts with the Core's Customer domain object to obtain the email data.

GetEmailCommand

Cortex API communicates with the Core through the Core API service layer.

The CoreLookup resource uses the GetEmailCommand service to retrieve a customer's email by the customer's GUID. The service's interface declares an inner interface for building the Core lookup command:

               <html><body>
<pre class="j-path">rest-resource-corelookup<span class="j-pathsep">/</span>src<span class="j-pathsep">/</span>main<span class="j-pathsep">/</span>java<span class="j-pathsep">/</span>com<span class="j-pathsep">/</span>extension<span class="j-pathsep">/</span>rest<span class="j-pathsep">/</span>core<span class="j-pathsep">/</span>command<span class="j-pathsep">/</span>user<span class="j-pathsep">/</span>GetEmailCommand.java</pre>
<pre class="java"><span class="j-jdoc">/**
 *
 * Command to get an email by user GUID.
 */
</span><span class="j-key">public interface </span>GetEmailCommand <span class="j-key">extends </span>Command&lt;EmailDto&gt; <span class="j-sym">{

  </span><span class="j-jdoc">/**
   * Builder interface for this Command.
   */
  </span><span class="j-key">interface </span>Builder <span class="j-key">extends </span>Command.Builder&lt;GetEmailCommand&gt; <span class="j-sym">{

    </span><span class="j-jdoc">/**
     * Set the user GUID for this Command.
     *
     * </span><span class="j-jdoc-key">@param </span><span class="j-jdoc">userGuid the User GUID.
     * </span><span class="j-jdoc-key">@return </span><span class="j-jdoc">This instance.
     */
    </span>Builder setUserGuid<span class="j-sym">(</span>String userGuid<span class="j-sym">)</span>;
  <span class="j-sym">}
}</span></pre>
</body></html>
            

The implementation of the interfaces are shown below. The inner interface is used for setting the GUID that Core receives. The outer interface injects and uses Cortex API customerRepository to find the appropriate customer in the database. The customerRepository is a part of Cortex API Data Access Layer that sits between the resources and the Core that handles all customer related queries.

               <html><body>
<pre class="j-path">rest-resource-corelookup<span class="j-pathsep">/</span>src<span class="j-pathsep">/</span>main<span class="j-pathsep">/</span>java<span class="j-pathsep">/</span>com<span class="j-pathsep">/</span>extension<span class="j-pathsep">/</span>rest<span class="j-pathsep">/</span>core<span class="j-pathsep">/</span>command<span class="j-pathsep">/</span>user<span class="j-pathsep">/</span>impl<span class="j-pathsep">/</span>GetEmailCommandImpl.java</pre>
<pre class="java"><span class="j-jdoc">/**
 *
 * Command to get email by user GUID. The DCAPI customer repository provides
 * a number of methods that wrap commands to help query for Customers.
 * We use a DTO to propagate the information that we need from a </span><span class="j-jdoc-link">{@link Customer}
 </span><span class="j-jdoc">* up to the higher level resource methods.
 */
</span>@Named
<span class="j-key">public class </span>GetEmailCommandImpl <span class="j-key">implements </span>GetEmailCommand <span class="j-sym">{

  </span><span class="j-key">private final </span>CustomerRepository customerRepository;

  <span class="j-key">private </span>String userGuid;


  <span class="j-jdoc">/**
   * Constructor.
   * </span><span class="j-jdoc-key">@param </span><span class="j-jdoc">customerRepository The Customer Repository.
   */
  </span>@Inject
  GetEmailCommandImpl<span class="j-sym">(
      </span>@Named<span class="j-sym">(</span><span class="j-str">&#34;customerRepository&#34;</span><span class="j-sym">)
      </span><span class="j-key">final </span>CustomerRepository customerRepository<span class="j-sym">) {
    </span><span class="j-key">this</span>.customerRepository = customerRepository;
  <span class="j-sym">}

  </span>@Override
  <span class="j-key">public </span>ExecutionResult&lt;EmailDto&gt; execute<span class="j-sym">() {

    </span><span class="j-key">return new </span>ExecutionResultChain<span class="j-sym">() {
      </span>@Override
      <span class="j-key">protected </span>ExecutionResult&lt;?&gt; build<span class="j-sym">() {
        </span>Customer customer = Assign.ifSuccessful<span class="j-sym">(</span>customerRepository.findCustomerByGuid<span class="j-sym">(</span>userGuid<span class="j-sym">))</span>;
        EmailDto emailDto = EmailDtoAssembler.assembleEmailDto<span class="j-sym">(</span>customer<span class="j-sym">)</span>;
        <span class="j-key">return </span>ExecutionResultFactory.createReadOK<span class="j-sym">(</span>emailDto<span class="j-sym">)</span>;
      <span class="j-sym">}
    }</span>.execute<span class="j-sym">()</span>;
  <span class="j-sym">}

  </span><span class="j-jdoc">/**
   * Builds a </span><span class="j-jdoc-link">{@link GetEmailCommand}</span><span class="j-jdoc">.
   */
  </span>@Named<span class="j-sym">(</span><span class="j-str">&#34;getEmailCommandBuilder&#34;</span><span class="j-sym">)
  </span><span class="j-key">public static class </span>BuilderImpl <span class="j-key">implements </span>Builder <span class="j-sym">{

    </span><span class="j-key">private final </span>GetEmailCommandImpl cmd;

    <span class="j-jdoc">/**
     * Constructor.
     * </span><span class="j-jdoc-key">@param </span><span class="j-jdoc">cmd GetEmailCommand instance.
     */
    </span>@Inject
    BuilderImpl<span class="j-sym">(</span><span class="j-key">final </span>GetEmailCommandImpl cmd<span class="j-sym">) {
      </span><span class="j-key">this</span>.cmd = cmd;
    <span class="j-sym">}

    </span>@Override
    <span class="j-key">public </span>GetEmailCommandImpl.Builder setUserGuid<span class="j-sym">(</span><span class="j-key">final </span>String userGuid<span class="j-sym">) {
      </span>cmd.userGuid = userGuid;
      <span class="j-key">return this</span>;
    <span class="j-sym">}

    </span>@Override
    <span class="j-key">public </span>GetEmailCommandImpl build<span class="j-sym">() {
      </span><span class="j-key">return </span>cmd;
    <span class="j-sym">}
  }
}</span></pre>
</body></html>
            

When a customer is successfully retrieved, the execute() method calls the assembler to construct a DTO. The assembler wraps the DTO in an ExecutionResult before sending the DTO to the resource.

To use a data access layer repository, the resource needs to reference the repository in blueprint.xml. The customerRepository reference in email-blueprint.xml is shown below:

               <html><body>
<pre class="j-path">rest-resource-corelookup<span class="j-pathsep">/</span>src<span class="j-pathsep">/</span>main<span class="j-pathsep">/</span>resources<span class="j-pathsep">/</span>OSGI-INF<span class="j-pathsep">/</span>blueprint<span class="j-pathsep">/</span>email-blueprint.xml</pre>
<pre class="j-text"><code>&lt;!-- import services --&gt;
&lt;reference id="resourceKernel"
	interface="com.elasticpath.rest.resource.ResourceServerKernel"/&gt;

&lt;reference id="resourceOperationContext"
	interface="com.elasticpath.rest.resource.ResourceOperationContext"/&gt;

&lt;reference id="customerRepository"
    interface="com.elasticpath.rest.resource.integration.epcommerce.repository.customer.CustomerRepository"/&gt;

&lt;!-- export services --&gt;
&lt;service ref="resourceServer"
	interface="com.elasticpath.rest.resource.ResourceServer"&gt;
	&lt;service-properties&gt;
		&lt;entry key="resourceServerName"&gt;
			&lt;ref component-id="resourceServerName"/&gt;
		&lt;/entry&gt;
	&lt;/service-properties&gt;
&lt;/service&gt;

&lt;service ref="permissionLookup"
	interface="com.elasticpath.rest.authorization.PermissionLookup"&gt;
	&lt;service-properties&gt;
		&lt;entry key="resourceServerNames"&gt;
			&lt;array&gt;
				&lt;ref component-id="resourceServerName"/&gt;
			&lt;/array&gt;
		&lt;/entry&gt;
	&lt;/service-properties&gt;
&lt;/service&gt;</code></pre>
</body></html>
            

Reading the DTO

Use a read strategy to read the DTO from the Core API service and pass its data into the resource's representation.

               <html><body>
<pre class="j-path">rest-resource-corelookup<span class="j-pathsep">/</span>src<span class="j-pathsep">/</span>main<span class="j-pathsep">/</span>java<span class="j-pathsep">/</span>com<span class="j-pathsep">/</span>extension<span class="j-pathsep">/</span>rest<span class="j-pathsep">/</span>resources<span class="j-pathsep">/</span>corelookup<span class="j-pathsep">/</span>command<span class="j-pathsep">/</span>impl<span class="j-pathsep">/</span>ReadProfileStrategy.java</pre>
<pre class="java"><span class="j-bkg">  </span><span class="j-jdoc">/**
   * Constructor.
   *
   * </span><span class="j-jdoc-key">@param </span><span class="j-jdoc">resourceServerName resource server name.
   * </span><span class="j-jdoc-key">@param </span><span class="j-jdoc">getEmailCommandBuilder Get email command.
   */
  </span>@Inject
  ReadProfileStrategy<span class="j-sym">(
      </span>@Named<span class="j-sym">(</span><span class="j-str">&#34;resourceServerName&#34;</span><span class="j-sym">)
      </span><span class="j-key">final </span>String resourceServerName,
      @Named<span class="j-sym">(</span><span class="j-str">&#34;getEmailCommandBuilder&#34;</span><span class="j-sym">)
      </span><span class="j-key">final </span>Provider&lt;GetEmailCommand.Builder&gt; getEmailCommandBuilder<span class="j-sym">) {

    </span><span class="j-key">this</span>.resourceServerName = resourceServerName;
    <span class="j-key">this</span>.getEmailCommandBuilder = getEmailCommandBuilder;
  <span class="j-sym">}


  </span>@Override
  <span class="j-key">public </span>ExecutionResult&lt;Representation&gt; execute<span class="j-sym">(</span><span class="j-key">final </span>Representation profile<span class="j-sym">) {

    </span><span class="j-key">return new </span>ExecutionResultChain<span class="j-sym">() {
      </span><span class="j-key">public </span>ExecutionResult&lt;?&gt; build<span class="j-sym">() {
        </span><span class="j-cmt">// Profile representation returned from the kernel.
        </span>ProfileRepresentation profileRepresentation = ResourceTypeFactory.adaptRepresentation<span class="j-sym">(</span>profile, ProfileRepresentation.<span class="j-key">class</span><span class="j-sym">)</span>;

        <span class="j-cmt">//Encoded IDs are used to be URI friendly so decode the ID before passing it down to be retrieved
        //from core.
        </span>String userGuid = Base32Util.decode<span class="j-sym">(</span>profileRepresentation.getProfileId<span class="j-sym">())</span>;
        GetEmailCommand getEmailCommand = getEmailCommandBuilder.get<span class="j-sym">()
          </span>.setUserGuid<span class="j-sym">(</span>userGuid<span class="j-sym">)
          </span>.build<span class="j-sym">()</span>;

        EmailDto emailDtoResult = execute<span class="j-sym">(</span>getEmailCommand<span class="j-sym">)</span>;
        EmailMutator emailMutator = EmailMutator.create<span class="j-sym">()</span>;

        Self profileSelf = profileRepresentation.getSelf<span class="j-sym">()</span>;
        String uri = URIUtil.format<span class="j-sym">(</span>resourceServerName, profileSelf.getUri<span class="j-sym">())</span>;
        Self self = SelfFactory.createSelf<span class="j-sym">(</span>uri, EmailRepresentation.TYPE, <span class="j-num">0</span><span class="j-sym">)</span>;
        emailMutator.setSelf<span class="j-sym">(</span>self<span class="j-sym">)</span>;

        ResourceLink linkToProfile = ResourceLinkFactory.createFromSelf<span class="j-sym">(</span>profileSelf, EmailResourceRels.PROFILE_REL,
          EmailResourceRels.EMAIL_REL<span class="j-sym">)</span>;
        emailMutator.addLink<span class="j-sym">(</span>linkToProfile<span class="j-sym">)</span>;
        emailMutator.setEmail<span class="j-sym">(</span>emailDtoResult.getEmail<span class="j-sym">())</span>;
        Representation emailRepresentation = emailMutator.getRepresentation<span class="j-sym">()</span>;
        <span class="j-key">return </span>ExecutionResultFactory.createReadOK<span class="j-sym">(</span>emailRepresentation<span class="j-sym">)</span>;
      <span class="j-sym">}
    }</span>.execute<span class="j-sym">()</span>;
  <span class="j-sym">}</span></pre>
</body></html>
            

As you can see, before getEmailCommand.execute() can fetch the DTO, the profile's ID is decoded. This is because the Cortex API encodes IDs so that they are compatible with URIs. To convert IDs into a URI compatible form and back, Cortex API uses a Base32Util utility class.

After the profile ID is decoded, the injected GetEmailCommand.Builder builds GetEmailCommand, using the decoded profile ID as a parameter. After executing the command, the Email DTO's data is passed to the resource's mutator.

Like the resource in the previous tutorial, the read strategy must be included in dcapi-resource-corelookup\src\main\resources\spring\applicationContext-resource-server.xml, injected into the resource operator, and executed in the processRead method. This will integrate the read strategy with the rest of the resource.