REQUEST_SIMPLE_READ

Description: Used for implementing code extensions that can be invoked as an N4 REST web service. When the expected parameters are passed to the code extension, it returns a string value. N4 extracts input parameters from the URL query parameters. The string output is returned in the HTTP response body. N4 requires a user name, password, N4 scope values, and a code extension name to be sent as part of the invocation of the REST web service. See REST API User Documentation under Code Extension User Guidelines in the the N4 3.0 SDK manualfor details about creating and configuring the N4 REST web service.

Abstract Base Class: AbstractSimpleRequest

Method: AbstractJSONDomainQueryExecutor.getConverter()

Interface: ESimpleReadRequest

Module: Framework

Version Added: 2.6

Requires Code Extension Name or Name Pattern: No

Code Extension Name or Name Pattern: N/A

Where to Specify Code Extensions of this Type: To configure a code extension of this type, you must:

  1. Create and enable a custom code extension that passes:

  1. Scope coordinates as follows: http://yourserver/apex/api/codeextension?extensionname=ExampleHelloWorldService&operatorId=OPR&complexId=CPLX&facilityId=FAC&yardId=YARD

  1. Parameters prefixed by PARM_. For example, if you have a parameter named RELATIVE_TIME, the REST parameter should be sent as PARM_RELATIVE_TIME

  1. Create a dedicated user that has a role with the following privilege enabled: ‘Execute Code Extensions via REST Protocol (on page 1)’

  2. For authorization, add the dedicated user with the "Universal Query API Access - Allow" privilege.

  3. For authentication, uses HTTP Basic Authentication. This means that the HTTP Header name must be 'Authorization', and the value 'user:pass', where 'user' is the user name and 'pass' is the password, must be Base64 encoded.

  4. Enable the N4 setting FRMCARINA032 (CODE_EXTENSION_BY_REST_ENABLE) (on page 1) at a scope level that is appropriate to the task.

For example, if you are creating a scoped copy of the system-seeded UpdateCheLastKnownYardPosition code extension, which uses this type, you would enable that setting at the Yard scope. Or, if you create a custom code extension to obtain all berthings across the facility, you could scope it at the Complex, Operation, or Global scope, depending on your preference.

System-Seeded Code Extensions Using this Type: UpdateCheLastKnownYardPosition

 

Code Example

The following sample code implements a custom REST web service for creating a berth scheduler.

To view the JSON formatted, use http://www.jsoneditoronline.org.

The URL will be something like this:

http://localhost:8280/apex/api/codeextension?extensionname=BerthSchedulerJSONDataExtract&PARM_RELATIVE_TIME=CURRENT_MONTH&operatorId=TRNG

The sample code:

<?xml version="1.0" encoding="UTF-8"?>

<cnx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schemas/cnx.xsd">

  <entity id="com.navis.extension.business.Extension">

    <field id="extName">BerthModelJSONDataExtract</field>

    <field id="extLang">GROOVY</field>

    <field id="extType">REQUEST_SIMPLE_READ</field>

    <field id="extVersion">3</field>

    <field id="extEnabled">true</field>

    <field id="extScopeLevel">1</field>

    <field id="extCreator">admin</field>

    <field id="extChanged">2013-01-04T10:55:38 -0800</field>

    <field id="extSysSeeded">false</field>

    <field id="extContents"><![CDATA[/*

* Copyright (c) 2013 Navis LLC. All Rights Reserved.

*

*/

 

package extension.groovy

 

import com.navis.external.framework.web.service.AbstractJSONDomainQueryExecutor

import com.navis.framework.metafields.MetafieldId

import com.navis.framework.metafields.MetafieldIdFactory

import com.navis.framework.portal.QueryUtils

import com.navis.framework.portal.UserContext

import com.navis.framework.portal.query.DomainQuery

import com.navis.framework.portal.query.PredicateFactory

import com.navis.yard.YardEntity

import com.navis.yard.YardField

import org.apache.commons.lang.StringUtils

 

/**

*  use PARM_BERTH_NAME to narrow down to berth. returns all if requested or is narrowed by login scopes

*/

public class BerthModelJSONDataExtract extends AbstractJSONDomainQueryExecutor {

  @Override

  protected DomainQuery getQuery(UserContext inContext, Map inParameters) {

    // this gets everything. Pass in the BERTH Model NAME

    DomainQuery q = QueryUtils.createDomainQuery(YardEntity.BERTH_USER_RANGE);

    q.addDqField(YardField.UBR1_D_SEQUENCE);

    q.addDqField(YardField.UBR_CODE);

    q.addDqField(YardField.UBR_NAME);

    q.addDqField(YardField.UBR1_D_START_LOC_CM);

    q.addDqField(YardField.UBR1_D_END_LOC_CM);

    q.addDqField(YardField.UBR_BERTH_RANGE_TYPE);

       q.setScopingEnabled(false);

    String name = inParameters.get("BERTH_NAME");

    MetafieldId BERTH_NAME = MetafieldIdFactory.getCompoundMetafieldId(YardField.UBR_OWNING_BERTH_MODEL, YardField.BRM_NAME);

 

    if (StringUtils.isNotEmpty(name)) {

      q.addDqPredicate(PredicateFactory.eq(BERTH_NAME, name))

    }

    return q;

  }

}]]></field>

    <field id="extCreated">2013-01-04T10:54:37 -0800</field>

    <field id="extChanger">admin</field>

  </entity>

  <entity id="com.navis.extension.business.Extension">

    <field id="extName">BerthSchedulerJSONDataExtract</field>

    <field id="extLang">GROOVY</field>

    <field id="extType">REQUEST_SIMPLE_READ</field>

    <field id="extVersion">10</field>

    <field id="extEnabled">true</field>

    <field id="extScopeLevel">1</field>

    <field id="extCreator">admin</field>

    <field id="extChanged">2013-01-08T14:16:13 -0800</field>

    <field id="extSysSeeded">false</field>

    <field id="extContents"><![CDATA[/*

* Copyright (c) 2013 Navis LLC. All Rights Reserved.

*

*/

 

package extension.groovy

 

import com.navis.argo.ArgoField

import com.navis.argo.ArgoRefField

import com.navis.external.framework.request.ESimpleResponseConverter

import com.navis.external.framework.web.service.AbstractJSONDomainQueryExecutor

import com.navis.external.framework.web.service.DefaultJSONResponseConverter

import com.navis.framework.business.atoms.PredicateVerbEnum

import com.navis.framework.business.atoms.RelativeTimeEnum

import com.navis.framework.metafields.MetafieldId

import com.navis.framework.metafields.MetafieldIdFactory

import com.navis.framework.portal.Ordering

import com.navis.framework.portal.QueryUtils

import com.navis.framework.portal.UserContext

import com.navis.framework.portal.context.UserContextUtils

import com.navis.framework.portal.query.DomainQuery

import com.navis.framework.portal.query.PredicateFactory

import com.navis.framework.util.internationalization.ITranslationContext

import com.navis.vessel.VesselEntity

import com.navis.vessel.VesselField

import com.navis.vessel.api.VesselVisitField

import com.navis.vessel.business.atoms.BerthSideTypeEnum

import org.apache.commons.lang.StringUtils

 

/**

*    http://localhost:8280/apex/api/codeextension?extensionname=BerthSchedulerDataExtract

*    <p/>

*    or with parameters

*

*     http://localhost:8280/apex/api/codeextension?extensionname=BerthSchedulerJSONDataExtract&PARM_RELATIVE_TIME=LAST_SEVEN_DAYS&operatorId=TRNG

*/

public class BerthSchedulerJSONDataExtract extends AbstractJSONDomainQueryExecutor {

  @Override

  protected DomainQuery getQuery(UserContext inContext, Map inParameters) {

 

    MetafieldId BERTH_VVD_ID =

      MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_VVD, VesselVisitField.VVD_ID);

 

    MetafieldId INBOUND_VOYAGE = MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_VVD, VesselVisitField.VVD_IB_VYG_NBR);

    MetafieldId OUTBOUND_VOYAGE = MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_VVD, VesselVisitField.VVD_OB_VYG_NBR);

 

    MetafieldId BERTH_VESSEL = MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_VVD, VesselField.VVD_VESSEL);

 

    MetafieldId BERTH_VESSEL_CLASS = MetafieldIdFactory.getCompoundMetafieldId(BERTH_VESSEL, VesselField.VES_VESSEL_CLASS);

    MetafieldId BERTH_VESSEL_NAME = MetafieldIdFactory.getCompoundMetafieldId(BERTH_VESSEL, VesselField.VES_NAME);

    MetafieldId BERTH_VESSEL_CLASS_ID = MetafieldIdFactory.getCompoundMetafieldId(BERTH_VESSEL_CLASS, VesselField.VESCLASS_ID);

    MetafieldId BERTH_SHIP_LOA = MetafieldIdFactory.getCompoundMetafieldId(BERTH_VESSEL_CLASS, VesselField.VESCLASS_LOA_CM);

    MetafieldId BERTH_SHIP_WIDTH = MetafieldIdFactory.getCompoundMetafieldId(BERTH_VESSEL_CLASS, VesselField.VESCLASS_BEAM_CM);

 

    MetafieldId BERTH_QUAY_ID = MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_QUAY, ArgoField.QUAY_ID);

    MetafieldId BERTH_QUAY_NAME = MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_QUAY, ArgoField.QUAY_NAME);

 

    MetafieldId BIZ_UNIT = MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_VVD, VesselVisitField.VVD_BIZU);

    MetafieldId LINE_OPERATOR = MetafieldIdFactory.getCompoundMetafieldId(BIZ_UNIT, ArgoRefField.BZU_ID);

    MetafieldId SERVICE = MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_VVD, VesselVisitField.VVD_SERVICE);

    MetafieldId SERVICE_NAME = MetafieldIdFactory.getCompoundMetafieldId(SERVICE, ArgoRefField.SRVC_NAME);

 

    MetafieldId EST_LOAD = MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_VVD, VesselVisitField.VVD_ESTMC_LOAD);

    MetafieldId EST_DISCHARGE = MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_VVD, VesselVisitField.VVD_ESTMC_DISCHARGE);

    MetafieldId EST_RESTOW = MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_VVD, VesselVisitField.VVD_ESTMC_RESTOW);

    MetafieldId EST_SHIFT = MetafieldIdFactory.getCompoundMetafieldId(VesselField.BRTHG_VVD, VesselVisitField.VVD_ESTMC_SHIFT);

 

    DomainQuery q = QueryUtils.createDomainQuery(VesselEntity.VESSEL_VISIT_BERTHING);

    q.addDqField(BERTH_VVD_ID);

    q.addDqField(BERTH_VESSEL_NAME);

    q.addDqField(VesselField.BRTHG_SHIP_SIDE_TO);

    q.addDqField(BERTH_QUAY_ID);

    q.addDqField(BERTH_QUAY_NAME);

    q.addDqField(VesselField.BRTHG_E_T_A);

    q.addDqField(VesselField.BRTHG_E_T_D);

 

    q.addDqField(BERTH_VESSEL_CLASS_ID);     // for debugging to change data

    q.addDqField(BERTH_SHIP_LOA);

    q.addDqField(BERTH_SHIP_WIDTH);

 

    q.addDqOrdering(Ordering.asc(VesselField.BRTHG_E_T_A));

    q.addDqOrdering(Ordering.asc(BERTH_QUAY_NAME));

 

    q.addDqField(LINE_OPERATOR);

    q.addDqField(SERVICE_NAME);

    q.addDqField(INBOUND_VOYAGE);

    q.addDqField(OUTBOUND_VOYAGE);

 

    q.addDqField(EST_LOAD);

    q.addDqField(EST_DISCHARGE);

    q.addDqField(EST_RESTOW);

    q.addDqField(EST_SHIFT);

 

    // Predicate for relative time which is optional

    String time = inParameters.get("RELATIVE_TIME");

    if (StringUtils.isNotBlank(time)) {

      RelativeTimeEnum timeEnum = RelativeTimeEnum.getEnum(time);

      q.addDqPredicate(PredicateFactory.createPredicate(inContext, VesselField.BRTHG_E_T_A, PredicateVerbEnum.TIME_IS, timeEnum));

    }

 

    return q;

  }

 

 

  //script runner to generate the variform

  public String generateVariformColumns() {

    DomainQuery q = getQuery(UserContextUtils.getSystemUserContext(), new HashMap());

    StringBuilder buf = new StringBuilder();

    for (String field : q.getFields()) {

      buf.append("<column fieldId=\"" + field + "\"/>\n");

    }

    return buf.toString();

  }

 

  protected ESimpleResponseConverter getConverter() {

    if (_converter == null) {

      _converter = new BerthFieldConverter();

    }

    return _converter;

  }

 

  private static class BerthFieldConverter extends DefaultJSONResponseConverter {

    @Override

    public Object translateValue(ITranslationContext inContext, MetafieldId inFieldId, Object inFieldValue) {

      if (inFieldValue instanceof BerthSideTypeEnum) {

        return ((BerthSideTypeEnum) inFieldValue).getName();

      } else if (inFieldValue instanceof Date) {

        // return java millis

        return ((Date) inFieldValue).getTime();

      }

      return super.translateValue(inContext, inFieldId, inFieldValue);

    }

  }

 

  private BerthFieldConverter _converter;

}]]></field>

    <field id="extCreated">2013-01-04T11:02:20 -0800</field>

    <field id="extChanger">admin</field>

  </entity>

  <entity id="com.navis.framework.navigation.business.CustomNode">

    <field id="custnodeVariformId">CUSTOM_BERTHINGS</field>

    <field id="custnodeMenuContext">/ulc/ApexNavigationTree.xml</field>

    <field id="custnodeScopeLevel">1</field>

    <field id="custnodeId">CUSTOM_NODE_BERTHINGS</field>

    <field id="custnodeChanged">2013-01-08T13:59:34 -0800</field>

    <field id="custnodeCreator">admin</field>

    <field id="custnodeParentId">MID_VESSEL</field>

    <field id="custnodePosition">AFTER_NODE</field>

    <field id="custnodeLabel">Berthing</field>

    <field id="custnodeCreated">2013-01-08T13:58:50 -0800</field>

    <field id="custnodeChanger">admin</field>

    <field id="custnodePrecedingId">VesselSchedule</field>

    <field id="custnodeEnabled">true</field>

  </entity>

  <entity id="com.navis.framework.configuration.variform.DbVariformFileDefinition">

    <field id="cfgvarVariformIds"><![CDATA[|CUSTOM_BERTHINGS|]]></field>

    <field id="cfgvarScopeLevel">1</field>

    <field id="cfgvarCreator">admin</field>

    <field id="cfgvarChanger">admin</field>

    <field id="cfgvarName">Berthings</field>

    <field id="cfgvarVariformXml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>

<variforms xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schemas/Variforms.xsd">

  <actions>

    <!--

        These are the most common used actions. Please verify needs and edit accordingly.

    -->

    <action id="view">view</action>

    <action id="create">create</action>

    <action id="update">update</action>

    <action id="delete">delete</action>

    <action id="query">query</action>

  </actions>

 

  <table id="CUSTOM_BERTHINGS">

unit

    <name>VesselVisitBerthing</name>

  </entity>

  <tableActions>

    <tableActionMode action="create" mode="allow" />

    <tableActionMode action="update" mode="allow" />

    <tableActionMode action="view" mode="allow" />

    <tableActionMode action="delete" mode="allow" />

  </tableActions>

 

    <column fieldId="brthgVvd.cvdCv.cvId"/>

<column fieldId="brthgVvd.vvdVessel.vesName"/>

<column fieldId="brthgShipSideTo"/>

<column fieldId="brthgQuay.quayId"/>

<column fieldId="brthgQuay.quayName"/>

<column fieldId="brthgETA"/>

<column fieldId="brthgETD"/>

<column fieldId="brthgVvd.vvdVessel.vesVesselClass.vesclassId"/>

<column fieldId="brthgVvd.vvdVessel.vesVesselClass.vesclassLoaCm"/>

<column fieldId="brthgVvd.vvdVessel.vesVesselClass.vesclassBeamCm"/>

<column fieldId="brthgVvd.vvdBizu.bzuId"/>

<column fieldId="brthgVvd.cvdService.srvcName"/>

<column fieldId="brthgVvd.vvdIbVygNbr"/>

<column fieldId="brthgVvd.vvdObVygNbr"/>

<column fieldId="brthgVvd.vvdEstMoveCount.mcLoad"/>

<column fieldId="brthgVvd.vvdEstMoveCount.mcDischarge"/>

<column fieldId="brthgVvd.vvdEstMoveCount.mcRestow"/>

<column fieldId="brthgVvd.vvdEstMoveCount.mcShift"/>

 

  </table>

</variforms>]]></field>

    <field id="cfgvarChanged">2013-01-08T13:59:06 -0800</field>

    <field id="cfgvarEnabled">true</field>

    <field id="cfgvarCreated">2013-01-08T13:54:54 -0800</field>

  </entity>

</cnx>