Skip Headers
Oracle® Retail POS Suite Implementation Guide, Volume 5 – Mobile Point-of-Service
Release 14.1
E54478-01
  Go To Table Of Contents
Contents

Previous
Previous
 
Next
Next
 

5 Mobile POS Extension Guidelines

This chapter provides some examples of common extensions and customizations to the Mobile POS server application. This includes how to override an existing service call, add a new service call, configure the InstructibleUIManager, and add a new service area. The screenshots for Eclipse are found in Appendix C.

Customize an Existing Service API

There are several points available for customizing an existing service call's behavior. The following are described in this section:

  • Override a service method

  • Customize the Tour Runner

  • Customize the target Tour

Service Method Override

Replacing or extending the behavior of the base service method requires the implementation of a new Java class and the update of a configuration file. For this case, assume that you want to add some additional validation logic to the results of the existing AuthWebService login API.

  1. Create a new Eclipse project or update an existing one. For detailed instructions, see "Eclipse Project Creation" in Chapter 6.

  2. Create a new class by right-clicking on Java Resources under the mobilepos project. The New Java Class dialog appears. Provide a Java package and class name. Set the Superclass to the following:

    oracle.retail.stores.mobilepos.web.service.auth.AuthServiceImpl
    

    See Figure C-1.

  3. Press Finish. The new class is generated similar to the following example:

    package oracle.retail.stores.mobilepos.example;
    
    import oracle.retail.stores.mobilepos.web.service.auth.AuthServiceImpl;
    
    public class AuthServiceLoginExtension extends AuthServiceImpl
    {
    
    }
    
  4. Implement the extension by overriding the target method. See the following example:

    @Override
    public AuthStatusWithProfile login(String hardwareID, String locale)
    {
       AuthStatusWithProfile result = super.login(hardwareID, locale);
    
       // Do some additional validation here
    
       ContextError someError =
               new ContextError("NEW_ERROR_CODE", "Some error message.");
    
       result.addError(someError);
       return result;
    }
    
  5. Update the ServiceContext.xml file to set the custom class as the implementation for the AuthWebService. See the following example:

    <bean id="service_AuthService"
          class="oracle.retail.stores.mobilepos.example.AuthServiceLoginExtension"
          lazy-init="true"
          singleton="true"/>
    
  6. Build and deploy the war file to test.

Customize the Tour Runner

You can also change an existing API's behavior by customizing the Tour Runner configuration to execute a tour differently, execute a different tour, or handle additional tour parameters by changing the launch and return shuttles.

Tour Runner Configuration

Start by examining the Tour Runner configuration script. The numbers in bold in Example 5-1 refer to major elements of the configuration that are described following the example.

Example 5-1 Tour Runner Configuration

<bean id="service_ItemInquiryTourRunner"
            class="oracle.retail.stores.mobilepos.tours.TourRunner"
            lazy-init="true" singleton="false">
    <property name="tourScript" (1)
        value="classpath://oracle/retail/stores/.../iteminquiry/ItemInquiry.xml"/>
    <property name="launchShuttleClass"  (2)
        value="oracle.retail.stores.....inquiry.ItemInquiryLaunchShuttle"/>
    <property name="returnShuttleClass"  (3)
        value="oracle.retail.stores.....inquiry.ItemInquiryReturnShuttle"/>
    <property name="managerData"> (4)
        <map>
            <entry key="UIManager" value-ref="service_ManagerData" />
        </map>
    </property>
    <property name="siteLetters"> (5)
        <map>
            <entry key="ShowItem" value="Next" />
            <entry key="ShowItemList" value="Next" />
        </map>
    </property>
</bean>

The following are the major elements of the Tour Runner configuration

  1. Tour script: Fully qualified file name of the tour XML defining the script to run, generally looked up on the CLASSPATH.

  2. Launch shuttle class: Fully qualified class name of the shuttle to use when the tour launches.

  3. Return shuttle class: Fully qualified class name of the shuttle to use when the tour exits.

  4. Manager data (optional): Reference to the UI Manager to use while running the tour.

  5. Site letters (optional): Collection of letters to mail from a particular site keyed by the situation that mails them.

The first three properties are required for a tour runner to execute successfully. Properties four and five are optional and generally are used as a pair. If you configure a UI Manager, you generally do so to enable letter manipulation.

InstructibleUIManager

As mentioned earlier, the InstructibleUIManager allows the tour runner to inject the letters that need to be sent when a show screen event is fired for a particular site. This behavior is needed since the Mobile POS server runs in a request-response mode instead of an interactive mode like the traditional POS. This manager extends the POSUIManager and overrides the showScreen behavior. When a POS tour site requests a screen or dialog to be displayed, the InstructibleUIManager intercepts the call and checks to see if any letters have been mapped for that particular site.

Example 5-2 Letters

<bean id="service_ItemInquiryTourRunner" …>
     ….
    <property name="siteLetters">
        <map>
            <entry key="ShowItem" value="Next" />
            <entry key="ShowItemList" value="Next" />
        </map>
    </property>
</bean>

If a letter has been mapped for the site making the request, the letter is mailed and the tour continues forward. If no letter is mapped, the default implementation throws an error by mailing the UnknownException letter, and the tour exits. In addition to providing letters for sites, the InstructibleUIManager can also accept instructions for a particular site. The default implementation supports two instructions:

  • Instruction.DoNotMail

  • Instruction.MailWithErrors:<Letter Name>

The first is used in cases where the POS tour will show a screen that merely shows some status and moves on without a letter getting mailed. In those cases, the value Instruction.DoNotMail should be provided. When the InstructibleUIManager receives this mapping, the showScreen call is exited without any letter being mailed.


Note:

Caution should be used when applying this instruction because the tour could hang if the site in question really should mail a letter and no letter is mailed.

The second instruction is used when an error is encountered, but you want the tour to continue on instead of exiting. The InstructibleUIManager will parse out the letter name and mail it while logging the error into the cargo. This allows tours that encounter recoverable errors to report the error back to the caller while continuing the tour.

Error Handling in the Mobile POS Server

Unlike the traditional POS, the Mobile POS server is designed to handle multiple registers running in the same Java virtual machine. As such, a site cannot assume a register for a particular action. The associated register must be provided. This is particularly important for error handling. To assist with this situation, the Mobile POS server provides an error code context to place errors into. The MobileErrorCodes and ContextError classes provide APIs for recording the errors into a specific error context.

MobileErrorCodes is a utility class that allows the implementer to simply provide an error code to record an error. The error message is pulled from the resource bundle based on a set naming standard (MobileApi.errorCode).

ContextError collects errors based on context and allows the service layer to retrieve and return them to the caller. This context is generally the register number requesting the action. Access to the context is provided by cargo classes that implement the MappableContextIfc interface. If the cargo does not implement this interface, the cargo class is reflectively scanned for no-argument methods that return a RegisterIfc so it can glean the context from the cargo. Once the context is established, the error code and any associated message are added to the ContextError collection keys by the given context.

Tour Runner Inputs and Outputs

The Tour Runner framework also allows you to customize the parameters provided to a tour and the results returned from a tour. The MobileTourInputParameters hierarchy of objects provides the input data for all default tour runners. These objects carry the data that is provided to each underlying tour as cargo attributes. The Status hierarchy of objects provides the output data and errors for all default tour runners. As discussed in the Status and Tour Parameter Object Frameworks section, these objects can be customized by implementing a custom object factory that extends the MobilePOSObjectFactory. For information on how these objects can be customized, see the Oracle Retail POS Suite Implementation Guide, Volume 2 - Extension Solutions.

Customize Tour

The tours executed by the tour runner are configured and extended just like existing POS tours. They are organized in a tour map XML file and referenced by XML file name. Any tour run by the Mobile POS server can be customized using the same mechanisms used to customize POS tours. There are two things you must keep in mind when reusing an existing POS tour in the Mobile POS server or implementing a new tour for the Mobile POS server:

  • The tours must be thread safe. Sites loaded into the foundation layer are treated as singletons. As such, each request thread can run through the site simultaneously, so all tour code must be thread safe.

  • The tour will need to be headless. Any existing tour will need to be analyzed to ensure all screen interactions are accounted for in the InstructibleUIManager letter mappings and all error conditions are handled properly. Any new tours should be written in such a way as to avoid the need for intermittent screen interaction.

For information on extending POS tours, see the Oracle Retail POS Suite Implementation Guide, Volume 2 - Extension Solutions.

Extend an Existing Service Area

When adding new functionality to an existing service area, you should follow the patterns established for these services:

  • Extend the service framework classes

    • Service interface

    • REST shell

    • Service implementation

  • Configure a new tour runner

  • Create tour input and output objects

Figure 5-1 Service Extension Model


The naming used here is an example. Follow your local naming conventions for the extensions. The new APIs should be declared on the interface and implemented on the two concrete classes. Be sure to annotate the WebServiceExt class and methods with REST annotations.

Example 5-3 Service Extension

@Path("auth/1.1")
public class AuthWebServiceExt extends AuthWebService implements AuthServiceExtIfc
{
    @Path("/login/extension/{storeID}/{registerID}")
    @GET
    @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
    public AuthStatusExt loginExtension(@PathParam("storeID") String storeID,
                             @PathParam("registerID") String registerID,
                             @QueryParam("locale") String locale)
    {
        return ((AuthServiceImplExt)serviceImplementation)
                             .loginExtension(storeID, registerID, locale);
    }
}

If the functionality of the new API requires a tour, identify an existing tour that performs the action or write a new one. You then need to configure a tour runner to execute that tour. For input into the tour, you may need a new Tour Parameters object. Again, use the framework provided and extend where appropriate. The same applies for the tour results. A new Status object may be required, and it too should take advantage of the Status hierarchy and extend where appropriate. The body of the new service API would look something like this:

Example 5-4 New Service API

// Validate the parameters
...

// Load the status object
YourStatus status = MobilePOSObjectFactory.getInstance().getYourStatus();

// Build tour parameters
YourTourParameters parms =
        MobilePOSObjectFactory.getInstance().getYourTourParameters();

parms.setParameterValue1(parameter1);
parms.setParameterValue2(parameter2);

// launch tour
try
{
    MobileTourResultIfc result = runTour(parms);
    if (result.getTourResult() instanceof YourStatus)
    {
        status = (YourStatus)result.getTourResult();
        return status;
    }

    logger.warn("Invalid result from tour: " + result);
    return null;
}
catch (Exception e)
{
    return MobilePOSObjectFactory.getInstance().getYourStatus(toErrorCode(e));
}

Once all of the classes are in place, update the ServiceContext.xml file as described in the previous section to configure the new tour runner and update the implementation class for the extended service.

Adding a New Service Area

Much like adding a new API to an existing service area, adding a new service area involves following the frameworks available. Take advantage of the base classes described in the previous sections to bootstrap your efforts. Be sure to distinguish your services by placing them on REST paths that do not conflict with the shipped services.

Customizing Authentication

The default authentication scheme uses the store database to read employee credentials. If you want to use a different repository for authentication, you need to update both authentication mechanisms described in the overview. For the application server plug-in, you need to provide a new implementation that uses the other repository. If you have already developed such a plug-in for any of the other POS Suite web applications, you should be able to reuse it. The only additional requirement the Mobile Server has over the other POS Suite web applications is support for the VersionableApplicationProvider interface. This interface is required to support the import of the Jersey libraries into the Mobile Server application server domain.

You also need a custom POS tour to access the alternate repository. Again, if POS has been customized to use this repository, you should be able to reuse that custom tour from the Mobile Server. You just need to update the login tour runner configuration (service_LoginTourRunner in ServiceContext.xml) to point to this alternate tour.

Working with Device Profiles

Device profiles provide a way to configure the handheld devices as registers and provide them with settings that are shared across the devices. The device profiles are stored in the DeviceContext.xml file under the
device_MobileRegisterProfileConfiguration bean key. The profile configuration consists of two main areas: device-to-register mappings and device settings.

Device Mappings

The device mapping section allows you to map a unique hardware identifier to a register in a store.

Example 5-5 Device Mappings

<property name="deviceMappings">
<map>        
    <entry key="Hardware ID 1">
        <bean class="oracle.…..RegisterProfileConfiguration.StoreRegisterPair">
            <property name="storeID" value="04241" />
            <property name="registerID" value="100" />
        </bean>
    </entry>
    <entry key="Hardware ID 2">
        <bean class="oracle….RegisterProfileConfiguration.StoreRegisterPair">
            <property name="storeID" value="04241" />
            <property name="registerID" value="101" />
        </bean>
    </entry>
</map>
</property>

The default implementation uses the UVID for iOS devices, but any unique ID can be configured. The installer allows for five devices to be configured, but there is no limit to the number of devices that can be in this map.


Note:

The register IDs are assumed to be a contiguous set, so it is best to keep the mobile register IDs separate from the traditional POS register IDs.

Device Settings

The second set of information available in the device profile is configuration settings. These settings apply to all devices using a device profile. There are three types of setting supported: configuration settings, POS parameters, and reason codes.

Configuration Settings

This set of key/value pairs represents configuration information used by mobile devices that fall outside the other two areas.

Example 5-6 Configuration Settings

<property name="configurationSettings">
    <map>
        <entry key="serviceCallTimeout" value="30"/>
        <entry key="serviceCallTenderTimeout" value="300"/>
        <entry key="inactiveWarningTimeout" value="840"/>
        <entry key="inactiveLogoutTimeout" value="900"/>
     </map>
</property>

The default settings deal with various timeout values, but any key/value pair can be used. To add a new setting, edit the DeviceContext.xml file and insert the new key/value pair. All mobile devices receive the new setting during login.

POS Parameters

This set of values represents the POS parameters returned to the mobile device.


Note:

All the mobile devices running on the same Mobile POS server share the same parameter values. If any parameter values are changed, all the mobile devices get the same updates.

Example 5-7 POS Parameters

<property name="parameterNames">
    <list>
        <value>CreditCardsAccepted</value>
        <value>GiftCardsAccepted</value>
        <value>TimeoutInactiveWithoutTransaction</value>
        <value>TimeoutInactiveWithTransaction</value>
        <value>IdentifyCashierEveryTransaction</value>
    </list>
</property>

The Mobile POS server resolves each parameter name to its configured value and returns the name/value pair to the mobile device as part of the profile. Only parameters that have a direct affect on the UI should be included in the list. Parameters affecting the POS tours used by the server API need not be included.

Reason Codes

Much like the POS parameter list, this property lists the reason code sets that should be returned to the mobile device as part of the profile.

Example 5-8 Reason Codes

<property name="reasonCodeSetNames">
    <list>
        <value>PriceOverrideReasonCodes</value>
        <value>ItemDiscountByAmount</value>
        <value>ItemDiscountByPercentage</value>
        <value>TransactionDiscountByAmount</value>
        <value>TransactionDiscountByPercentage</value>
        <value>TransactionSuspendReasonCodes</value>
    </list>
</property>

The Mobile POS server resolves each reason code name to its configured value set and returns it to the mobile device as part of the profile. The default set reflects the reason codes available in the POS sample data. If you customize the reason codes, be aware that this list needs to be updated and the Mobile POS UI needs to reflect those changes.