3 Creating a Published Business Service

This chapter contains the following topics:

3.1 Understanding Published Business Services

A published business service gives exposure to one or more business services by providing an interface that is available to the public as a consumable web service. A published business service is a Java class that contains business service methods where the actual business logic is performed.

You use JDeveloper, JD Edwards EnterpriseOne business services framework, and the Java programming language to create published business services. The business service framework provides a set of foundation packages that helps you create published business services. Each foundation package contains a set of interfaces and related classes. All published business service classes extend from the PublishedBusinessService foundation class. Code samples are provided throughout this chapter to demonstrate the general concepts for creating a published business service. Rules and best practices are discussed for each topic, if appropriate.

The following class diagram shows the main published business service class (AddressBookManager) and the value object class (AddAddressBook) and its components:

Figure 3-1 Published business service class diagram

Description of Figure 3-1 follows
Description of "Figure 3-1 Published business service class diagram"

These features are illustrated in the published business service class diagram:

  • AddressBookManager extends foundation class PublishedBusinessService.

  • AddAddressBook extends ValueObject.

  • ConfirmAddAddressBook extends MessageValueObject.

  • All components of AddAddressBook and ConfirmAddAddressBook extend ValueObject.

3.2 Developing a Published Business Service

A published business service contains multiple Java classes, including a published business service class and value object classes. The published business service class contains public methods that are exposed to the public. These public Java methods are wrappers for business services where the actual business logic is performed.

After a business service is published, you cannot change the name and signature of the business service without affecting the consumers of that service. If you change an underlying business service that the published method exposes, then you change the signature and contract of the published business service. Because JD Edwards EnterpriseOne is not providing a merge of new and existing software, when you update or upgrade your system, any business services that you have changed will be overwritten by new JD Edwards EnterpriseOne code. If you need to change an underlying business service, copy the existing business service into a new Object Management Workbench (OMW) object and name the OMW object as a version of the original business service. You also create a new published business service method that includes the versioned business service.

3.2.1 Creating a Transaction in a Published Business Service

A published business service class has a public method and a protected method that work together to expose a web service operation. The public method is exposed as the web service and acts as a wrapper method that passes a null to the context and connection parameters of the protected method. By passing null for these objects, the wrapper method identifies that this is the outermost call; that is, this is the web service. When a null context is passed, the protected method creates a context object that contains either a default manual connection or an auto commit connection for processing a transaction. Two methods with the same context name but different parameters exist. The context object that is used depends on whether you initiate a manual commit or auto commit connection. After the context object is created, the protected method starts processing by calling startPublishedMethod. All calls after startPublishedMethod are tied together by the context object. By passing null for the connection object, the wrapper method indicates that the default connection should be used for all operations. If a JD Edwards EnterpriseOne customer needs to extend a published business service by creating their own published business service and calling an existing JD Edwards EnterpriseOne published business service, the connection must be passed and it would not be null.

See Auto Commit.

The context object and the connection object are passed to the business service method where the business function call is made. After returning from the business service, the context object is sent to finishPublishedMethod to commit the default transaction in the case of manual commit, and then to the close method to close and clean up all outstanding connections.

This code sample shows creating and passing the context object:

 public ConfirmAddAddressBook addAddressBook(AddAddressBook vo) 
throws BusinessServiceException {
       return (addAddressBook(null,null, vo));
   }
    protected ConfirmAddAddressBook addAddressBook
                                (IContext context,IConnection 
                                connection, AddAddressBook vo) throws 
                                BusinessServiceException{
       //perform all work within try block, finally will clean up any 
       //connections
       try {
           // call start published method, passing null, 
           //will return context object so BSFN can be called later
           //used to indicate transaction boundary as well as used for 
           //logging
           //RI: Start Implicit Transaction
           context = startPublishedMethod(context, 
                "addAddressBook");
           // create a new internal vo based on the external vo passed 
           InternalAddAddressBook internalVO= new 
              InternalAddAddressBook();
           messages.addMessages(vo.mapFromPublished(context, 
              internalVO));
          // start business service addAddressBook passing context 
             and internal VO
           //RI: Published Business Service Calling Business Service
           E1MessageList messages = AddressBookProcessor.addAddressBook
           (context,connection,internalVO);
           // Published Business Service will send either warnings in 
              the Confirm Value Object or throw a published business 
              service Exception.
           //a return status of 2 is an error, throw the exception
           if (messages.hasErrors()) {
               // get the string representation of all the messages
                //RI: Error Handling
               String error = messages.getMessagesAsString()); 
               // Throw new BusinessServiceException(error);
               throw new BusinessServiceException(error,context);
           }
           // exception was not thrown, so create the confirm VO from 
              internal VO
           ConfirmAddAddressBook confirmVO = new ConfirmAddAddressBook
             (internalVO);
           confirmVO.setE1MessageList(messages);
           // call finish published method, passing the context  
           //to commit transaction(if no exceptions), as well as use 
           //in logging
           finishPublishedMethod(context, "addAddressBook");
           // return confirm VO, filled with return values and messages
           return confirmVO;
       } finally {
           //clean up any remaining connections and resources.  
           close(context,"addAddressBook");
       }

3.3 Managing Published Business Service Components

Naming conventions and concepts for creating published business service classes, methods, value objects, and fields are discussed in the following sections. Code samples are provided as examples for you to follow. Rules and best practices are also discussed where appropriate.

3.3.1 Published Business Service Class Names

The naming convention for a published business service class is the description name of the system code with Manager added to the end of the name; for example, AddressBookManager. Other examples of published business service class names are ProcurementManager and SalesOrderManager.

This code sample shows the naming convention for a published business service class:

   public class AddressBookManager extends 
   PublishedBusinessService {
   ....
   }

3.3.2 Published Business Service Method Names

The naming convention for a published business service method is to use a functional description prefaced by an action verb that describes the processing that will occur. For example, for a published business service method that adds an address book record to the database, an appropriate published business service method name is addAddressBook. The business service public method uses the same name as the published business service method.

This code sample shows the naming convention for a published business service method:

   public ConfirmAddAddressBook addAddressBook
   (AddAddressBook vo) throws BusinessServiceException{
   ...
   }

3.3.3 Published Business Service Value Object Names

The input and output parameters of the published business service are called published value objects. The published business service method takes one value object as its input parameter and returns one value object as its output parameter.

This code sample shows the naming convention for published value objects:

    public ConfirmAddAddressBook addAddressBook 
(AddAddressBook vo) throws BusinessServiceException {
   ...
   }

3.3.3.1 Published Business Service Variable Names

The variable name should clarify the type of data in the field or compound. For example, if multiple entity type objects exist, the class called Entity would be the data type, but ProcessPurchaseOrder would contain objects of type Entity called supplier and shipTo. In this example, the Entity class can be reused from the EntityProcessor utility business service.

In the following code sample, the AddAddressBook value object has three top-level field names and contains an entityAddress, which is subsequently made up of an entity with three fields and an address with ten fields:

public class AddAddressBook extends ValueObject implements 
Serializable{
       private EntityAddress entityAddress = new EntityAddress();
       private String entityName;
       private String entityTypeCode;
       private String version;
   ....
   }
   public class EntityAddress extends ValueObject implements 
   Serializable {
       private Entity entity = new Entity();
       private Address address = new Address();
   ....
   }
   public class Address extends ValueObject implements Serializable{
       private String mailingName;
       private String addressLine1;
       private String addressLine2;
       private String addressLine3;
       private String addressLine4;
       private String city;
       private String countyCode;
       private String stateCode;
       private String postalCode;
       private String countryCode;
   ....
   }
   public class Entity extends ValueObject implements Serializable{
      private Integer entityId;
      private String entityLongId;
      private String entityTaxId;
   ....
   }

3.3.4 Creating a Published Business Service Class

The business service foundation provides a Published Business Service wizard that helps you create published business service classes. The wizard prompts you for a published business service name, an input value object name, an output value object name, and a method name. The wizard creates a Java code structure for a published business service class that can be published as a web service. This structure contains comments and TODO: tags to help you add the code to call mapping methods and business service methods.

See "Understanding Business Services" in the JD Edwards EnterpriseOne Tools Business Services Development Methodology Guide.

3.3.4.1 Rules

The published business service class extends the PublishedBusinessService foundation class, and the constructor must be public. This extension provides access to the transaction methods (startPublishedMethod and finishPublishedMethod) that are used in all of the published methods of a published business service class.

This code sample shows how to extend the published business service foundation class:

  public class AddressBookManager extends PublishedBusinessService {
       public AddressBookManager() {
       }
   ....
   }

3.3.5 Declaring Public Methods for a Published Business Service

Published business service classes expose public, nonstatic methods. Declaring a public method exposes it to third-party systems.

This code sample shows a published business service declaring a business service method:

  public ConfirmAddAddressBook addAddressBook
  (AddAddressBook vo) throws BusinessServiceException{
   ...
   }

When you use the Published Business Service wizard to create the published business service class, the wizard also creates a public and protected method. For additional methods, you can use code templates to generate Java code. The E1PM – EnterpriseOne Published Business Service Method code template generates code for both public and protected methods of a published business service class. You use a code template in the source code. After you generate code using the code template, you press the Tab key to move through the highlighted fields to complete the generated code. The generated code contains TODO: tags that help you.

3.3.6 Creating a Published Value Object

The business service foundation provides value object wizards that help you create value object classes that follow methodology rules for published value objects. The Value Object wizard creates objects based on database tables and business views for database operations or from the data structures defined within a business function.

When the wizard generates member variables for the published value object class, it uses the description that comes from the data dictionary item in the business function data structure or from table or business view columns as the variable name. If these are not the names that you want to use in your published interface, you can change them.

This code sample shows a generated variable:

   /**
    * Business Unit
    * An alphanumeric code that identifies a separate entity within a 
    * business for which you want to track costs. For example, a 
    * business unit might be a warehouse location, job, project, work 
    * center, branch, or plant.

    * EnterpriseOne Key Field: false
    * EnterpriseOne Alias: MCU
    * EnterpriseOne field length: 12
    */
    private String businessUnit = null;

You use the standard JDeveloper wizard to generate the get and set methods for the variables because the Value Object wizard does not generate these methods. For web services to be generated and deployed successfully, you must use J2EE standards for naming the get and set methods. J2EE standards for writing a field such as private String description would be:

public String getDescription(){
    return description;
 }
 public void setDescription(String description){
    this.description = description;
 }

For Boolean fields, the pattern is slightly different. J2EE standards for writing a field such as private Boolean isCreditExempt; would be:

public Boolean isIsCreditExempt(){
    return isCreditExempt;
 }
 public void setIsCreditExempt(Boolean isCreditExempt){
    this.isCreditExempt = isCreditExempt;
 }

3.3.6.1 Published Value Object Structure and Data Types

The published input value object must extend the ValueObject foundation class. The published confirm or response value object contains warning messages that were returned from the business processing and must extend the MessageValueObject foundation class. All published value objects must have a default constructor.

This table lists the valid data types for published value objects:

Valid Data Type Usage
java.lang.String Use for string or char fields in JD Edwards EnterpriseOne.
java.util.Calendar Use for JDEDate or UTIME fields in JD Edwards EnterpriseOne.
java.lang.Integer Use for MathNumeric fields defined with 0 decimals, for example, mnAddressNumber, mnShortItemNumber, and so on.
java.lang.BigDecimal Use for MathNumeric fields defined with >0 decimals, for example, mnPurchaseUnitPrice.
java.lang.Boolean Use for char fields specified only as true/false or 0/1 Boolean fields.

Value object classes can be reused when a business service calls a utility or for calls between business services that depend on one another—such as AddressBook and Supplier. For example, you can reuse the Entity class from the EntityProcessor utility business service by importing the class from the utility's package.

3.3.6.2 Web Service Considerations for Data Types and Variable Names

A published business service class is the foundation for creating a web service. The web services description language (WSDL) is an XML-based language that describes a web service. The WSDL describes all methods of the published business service as well as the input and output value objects for these methods. All classes that make up the highest-level value object are included in the WSDL description. For example, for the Procurement Manager web service, the operations that the WSDL exposes are processPurchaseOrder, getPurchaseOrder, and processPurchaseOrderAcknowledge. All value object classes that are associated with these operations are defined in the WSDL as well.

All classes that are used within a published business service must have a unique name, which you should consider when you reuse value objects across published business services. Member variable names within the published business service value object class must be unique if they are of different object types. For example, the hierarchy of ProcessPurchaseOrder contains two classes representing financial data—one at the header level and one at the detail level. The header and detail are represented by unique classes because they are structured differently. Because both header and detail belong under the interface ProcessPurchaseOrder, the variable name referencing these object types must be unique; for example, financial and financialDetail.

The requirement for using unique variable names applies only to classes that have the same parent value object. You are not required to use unique variable names across value object classes. For example, both ProcessPurchaseOrder and ProcessPurchaseOrderAcknowledge have a header class, but the header classes are structured differently. Both of the member variables representing these classes can use the name header because they belong to different parent value objects. Classes that can be reused, such as PurchaseOrderKey, can have the same variable name across value objects.

The following examples show uniquely named classes that have member variables that are named the same:

Type Member Variable Name
ProcessPurchaseOrder
  PurchaseOrderHeader
    PurchaseOrderKey 
      Integer 
      String 
      String 
    UserReservedData 
      String 
      Integer
      BigDecimal
      Calendar 
    PurchaseOrderFinancial 
    PurchaseOrderDetail 
      PurchaseOrderFinancialDetail
header
  purchaseOrderKey
    documentNumber
    documentCompany
    documentType
  userReservedData
    userReservedCode
    userReservedNumber
    userReservedAmount
    userReservedDate
  financial
  detail
    financialDetail

Type Member Variable Name
ConfirmProcessPurchaseOrder
  ConfirmPurchaseOrderHeader
    PurchaseOrderKey
      Integer
      String
      String
    UserReservedData
      String
      Integer
      BigDecimal
      Calendar
    ConfirmPurchaseOrderFinancial
    ConfirmPurchaseOrderDetail
      ConfirmPurchaseOrderFinancialDetail
header 
  purchaseOrderKey
    documentNumber
    documentCompany
    documentType 
  userReservedData
    userReservedCode
    userReservedNumber
    userReservedAmount
    userReservedDate
  financial
  detail
    financialDetail
   

Type Member Variable Name
ProcessPurchaseOrderAcknowledge
  PurchaseOrderAcknowledgeHeader
    PurchaseOrderKey
       Integer
       String
       String
    UserReservedData
       String
       Integer
       BigDecimal
       Calendar
    PurchaseOrderAcknowledgeFinancial
    PurchaseOrderAcknowledgeDetail
       PurchaseOrderAcknowledgeFinancialDetail
header
   purchaseOrderKey
      documentNumber
      documentCompany
      documentType 
   userReservedData
      userReservedCode
      userReservedNumber
      userReservedAmount
      userReservedDate
   financial
   detail
      financialDetail

Type Member Variable Name
GetPurchaseOrder
  PurchaseOrderGetHeader
    PurchaseOrderKey
      Integer
      String
      String
    UserReservedData
      String
      Integer
      BigDecimal
      Calendar
    PurchaseOrderGetFinancial
    PurchaseOrderGetDetail
      PurchaseOrderGetFinancialDetail
purchaseOrderGetHeader
   purchaseOrderKey
      documentNumber
      documentCompany
      documentType 
   userReservedData
      userReservedCode
      userReservedNumber
      userReservedAmount
      userReservedDate
   financial
   detail
      financialDetail

Type Member Variable Name
ShowPurchaseOrder
  PurchaseOrderShowHeader
    PurchaseOrderKey
      Integer
      String
      String
    UserReservedData
      String
      Integer
      BigDecimal
      Calendar
    PurchaseOrderShowFinancial
    PurchaseOrderShowDetail
      PurchaseOrderShowFinancialDetail
header
   purchaseOrderKey
      documentNumber
      documentCompany
      documentType 
   userReservedData
      userReservedCode
      userReservedNumber
      userReservedAmount
      userReservedDate
   financial
   detail
      financialDetail

3.3.6.3 Rules

Follow these rules when you develop published business service value object classes:

  • Implement the serialize interface for all published value objects. This facilitates exposing the published business service as a web service.

  • Initialize published business service value object compound attributes. This is to prevent null pointer exceptions when the method calls accessors.

  • Expose published business service value object compound collections as arrays. Collection objects such as an ArrayList cannot be exposed from a web service at this time.

  • Do not change published value objects, because the change breaks the contract that was created by the original value object. This is to support backwards compatibility.

  • Do not add a new field, because this breaks the original contract that was set by the value object. You must create a new version of the value object and method.

  • Create response value objects that contain a complete message (more than just keys).

  • Place mappings between published and internal value objects in a method in the published value object.

3.3.6.4 Published Input Value Object

This code sample illustrates the code for a published input value object class:

public class AddAddressBook extends ValueObject implements 
Serializable{
       private EntityAddress entityAddress = new EntityAddress(); 
       // Compound attribute is initialized
       private String entityName; //Leaf attribute not initialized
       private String entityTypeCode;
       private String version;
   ....
   }
   public class EntityAddress extends ValueObject implements 
Serializable {
       private Entity entity = new Entity();
       private Address address = new Address();
   ....
   }
   public class Address extends ValueObject implements 
Serializable{
       private String mailingName;
       private String addressLine1;
       private String addressLine2;
       private String addressLine3;
       private String addressLine4;
       private String city;
       private String countyCode;
       private String stateCode;
       private String postalCode;
       private String countryCode;
   ....
   }
   public class Entity extends ValueObject implements 
Serializable{
      private Integer entityId;
      private String entityLongId;
      private String entityTaxId;
   ....
   }

3.3.6.5 Published Response Value Object

This code sample illustrates the code for a published response value object class:

public class ConfirmAddAddressBook extends MessageValueObject implements 
Serializable{
       private EntityAddress entityAddress = new EntityAddress(); 
       // Compound attribute is initialized
       private String entityName; 
       //Leaf attribute not initialized  
       private String entityTypeCode;
       private String version;
   ....
   }
   public class EntityAddress extends ValueObject implements Serializable {
       private Entity entity = new Entity();
       private Address address = new Address();
   ....
   }
   public class Address extends ValueObject implements Serializable{
       private String mailingName;
       private String addressLine1;
       private String addressLine2;
       private String addressLine3;
       private String addressLine4;
       private String city;
       private String countyCode;
       private String stateCode;
       private String postalCode;
       private String countryCode;
   ....
   }
   public class Entity extends ValueObject implements Serializable{
      private Integer entityId;
      private String entityLongId;
      private String entityTaxId;
   ....
   }

3.3.6.6 Mappings

The mapping between the published value object and the internal value object takes place in the published value object. You create a method for mapping fields from the published value object to the corresponding fields of the internal value object.

If you call the Formatter utility or a business service utility when mapping data from published to internal value objects, Oracle recommends that you create a method named mapFromPublished that returns an E1MessageList. The mapFromPublished method takes at a minimum the internal value object as a parameter. This method holds all of the mappings between the published value object and the internal value object. If a message could be returned to the published business service, you should create a method for mappings. You should always create a method to return messages when you call a business service utility or the Formatter utility during mapping. If no messages would be returned from mappings, you can have the method return void.

This code sample uses the mapFromPublished method and returns an E1MessagleList:

  public E1MessageList mapFromPublished(IContext context, RI_InternalAdd
AddressBook vo){
     E1MessageList messages = new E1MessageList();
     //set all internal VO attributes based on external VO passed in
        
     vo.setSzMailingName(this.getEntityAddress().getAddress().
getMailingName());
     vo.setSzAddressLine1(this.getEntityAddress().getAddress().
getAddressLine1());
     vo.setSzAddressLine2(this.getEntityAddress().getAddress().
getAddressLine2());
     vo.setSzAddressLine3(this.getEntityAddress().getAddress().
getAddressLine3());
     vo.setSzAddressLine4(this.getEntityAddress().getAddress().
getAddressLine4());
     vo.setSzCity(this.getEntityAddress().getAddress().getCity());
     vo.setSzState(this.getEntityAddress().getAddress().getStateCode());
     vo.setSzCountry(this.getEntityAddress().getAddress().getCountryCode());
     vo.setSzCounty(this.getEntityAddress().getAddress().getCountyCode());
     vo.setSzPostalCode(this.getEntityAddress().getAddress().
getPostalCode());
     vo.setMnAddressBookNumber(this.getEntityAddress().getEntity().
getEntityId());
     vo.setSzLongAddressNumber(this.getEntityAddress().getEntity().
getEntityLongId());
     vo.setSzTaxId(this.getEntityAddress().getEntity().getEntityTaxId());
     vo.setSzAlphaName(this.getEntityName());
     vo.setSzSearchType(this.getEntityTypeCode());
     vo.setSzVersion(this.getVersion());
     vo.setJdDateEffective(this.getEffectiveDate());
     //format business unit coming from published vo.
     String formattedMCU = null;
     String bu = this.getBusinessUnit();
     if(bu!=null && !bu.equals("")){
        try {
          formattedMCU = context.getBSSVDataFormatter().format(this.
getBusinessUnit(),"MCU");
          vo.setSzBusinessUnit(formattedMCU);
        }
        catch (BSSVDataFormatterException e) {
          context.getBSSVLogger().app(context,"Error when formatting Business
 Unit.",null,vo,e);
          //Create new E1 Message with error from exception
          messages.addMessage(new E1Message(context, "002FIS",this.
getBusinessUnit()));
        }
      }
        
        //phones loop through array
        //new arraylist
        RI_Phone phones[] = this.getPhones();
       if (this.getPhones()!=null){
           ArrayList phonesList = new ArrayList();
           for(int i=0; i<phones.length; i++){
              //create internal phone and add to array list

If an E1MessageList would never be returned, and the mappings are from internal to published response value objects, you can use an overloaded constructor for the internal value object mappings. If you have no calls to utilities or formatters, mapping can be done in the constructor. If the mappings are from published to internal value objects and no messages are being returned, you should create a mapFromPublished method that returns void.

This code sample uses an overloaded constructor for mapping:

     public ShowAddressBook(InternalGetAddressBook internalVO){
       if(internalVO.getQueryResults()!=null){
          this.setNumberRowsReturned(internalVO.getQueryResults().size());
          this.addressBook = new AddressBook[internalVO.getQueryResults().
size()];
          for(int i = 0;i<internalVO.getQueryResults().size();i++){
             AddressBook ab = new AddressBook(internalVO.getQueryResults(i));
             this.setAddressBook(i,ab);
          }
       }
   }

3.3.6.7 Data Type Transformation

When you map data between published and internal value objects, data type transformations may be required. The business service foundation provides methods and constructors that format data and transform data types. Data type transformations that are done in the mappings are:

  • Integer to and from MathNumeric

  • BigDecimal to and from MathNumeric

  • Boolean to and from String

3.3.6.8 Integer to and from MathNumeric and BigDecimal to and from MathNumeric

Mapping between published integer fields and internal math numeric fields requires a data type transformation. You use the set methods of the internal value object to make these transformations. An overloaded method takes either an integer or a math numeric data type when setting the field value.

The same rule applies to mapping between big decimal and math numeric fields. The business service foundation provides multiple math numeric constructors. The null check is performed because the constructor throws an error if a null parameter is passed.

This code sample shows set methods where a new math numeric data type is created by passing an integer type value or a big decimal type value:

---------------Integer to MathNumeric----------------------
public void setNumberField(Integer numberField){
   if(numberField!=null)
      this.numberField= new MathNumeric(numberField);
}
---------------BigDecimal to MathNumeric-------------------
public void setNumberField(BigDecimal numberField){
   if(numberField!=null)
      this.numberField= new MathNumeric(numberField);
}
---------------MathNumeric to BigDecimal--------------------
public void setNumberField(MathNumeric numberField){
   if(numberField!= null)
      this.numberField= numberField.asBigDecimal();
}
---------------MathNumeric to Integer-----------------------
public void setNumberField(MathNumeric numberField){
   if(numberField!= null)
      this.numberField= new Integer(numberField.intValue());
}

3.3.6.9 Boolean to and from String

A published Boolean field must be translated to an internal String type field. The business service foundation provides three ValueObject methods to assist you with this transformation. Because these methods are in the ValueObject class, they are available from all value objects. The methods are:

Method Usage
transformBooleanYN(Boolean) Returns a string of Y for passed value of true. Returns N for passed value of false. Returns null string for null Boolean.
transformBoolean01(Boolean) Returns a string of 1 for passed value of true. Returns 0 for passed value of false. Returns null string for null Boolean.
transformToBoolean(String) Returns a Boolean value that takes a string. A string of 1,Y,y returns true. A string of 0,N,n returns false. A null or incorrect string returns null.

This code sample shows the structure for each of the methods:

-----------------String to Boolean---------------------
//Use ValueObject (tools provided method) transformToBoolean.
//Tools method will account for both Y,y,N,n,0,1 values, null values 
//set Boolean to null
public void setIsSomething(String isSomething){ 
   this.isSomething= transformToBoolean(isSomething);
}
------------------Boolean to String----------------------              
//E1 needs to be researched to determine what values are valid for
//true and false values
//Use ValueObject (tools provided methods) transformBooleanYN or 
//transform Boolean01.
//Tools method will provide proper Boolean value for either Y/N or 
//0/1, null will result in null String
public void setIsSomething(Boolean isSomething){
   this.isSomething = transformBooleanYN(isSomething);
}
                 OR
public void setIsSomething(Boolean isSomething){
   this.isSomething = transformBoolean01(isSomething);

3.3.6.10 Data Formatter

In addition to mappings, you might need to format data coming from the published value object. For example, the JD Edwards EnterpriseOne database stores fields such as company (CO) and business unit (MCU) with preceding spaces or zeros. These fields should be formatted so that the preceding spaces and zeros are hidden from the published business service. The business service foundation utilities package provides formatting methods that enable you to pass in a value, and based on the data dictionary rules for the data dictionary item being passed in, formats the value accordingly.

You can use the code template E1DF – EnterpriseOne Data Formatter to generate code for data that requires formatting. The formatter code template generates the code and highlights variable names that you must change.

This sample code is generated by the EnterpriseOne Data formatter code template:

//format business unit coming from published vo.
        String formattedMCU = null;
        String bu = this.getBusinessUnit();
        if(bu!=null && !bu.equals("")){
           try {
             formattedMCU = context.getBSSVDataFormatter().format(
this.getBusinesUnit(),"MCU");
             vo.setSzBusinessUnit(formattedMCU);
           }
           catch (BSSVDataFormatterException e) {
             context.getBSSVLogger().app(context,"Error when 
formatting BusinessUnit.",null,vo,e);
             //Create new E1 Message with error from exception
             messages.addMessage(new E1Message(context, 
"002FIS",this.getBusinessUnit()));
          }
        }

3.4 Calling a Business Service

The published business service class exposes a public method as a web service operation. The business service method that the published business service class calls acts as a controller to the business logic.

3.4.1 Rules

These are the rules for a published business service method calling a business service method:

  • The signature for the business service static method must contain an IContext object, an IConnection object, and an internal value object.

  • The published business service method passes the IContext and IConnection objects to the business service, enabling the published business service to keep track of transaction information throughout the entire processing of the published business service.

  • The published business service method creates a new internal value object that is based on the external value object.

  • The business service static method returns an E1MessageList object, which contains an array of all error, warning, and information messages that occurred during processing and were set by the business function.

  • If the array contains an error message, the published business service must throw an exception using the text from the E1MessageList

  • If no error messages exist in the array, the business service returns a confirm value object to the published business service method caller.

    The confirm object is created when the business service passes the internal value object to the constructor for the published confirm value. All warnings and information messages that are returned from calling the business service are mapped to the confirm object.

This code sample shows implementation of these rules:

public ConfirmAddAddressBook addAddressBook(AddAddressBook vo) throws 
BusinessServiceException {
       return (addAddressBook(null, null, vo));
   }
   protected ConfirmAddAddressBook addAddressBook(IContext context, 
                                 IConnection connection, 
                                 AddAddressBook vo) throws 
BusinessServiceException {
        //perform all work within try block, finally will clean up any 
connections
       try {
           //Call start published method, passing context of null 
           //will return context object so BSFN or DB operation can 
           //be called later.
           //Context will be used to indicate default transaction 
           //boundary, as well as access to formatting and logging 
           //operations.
           context = startPublishedMethod(context, "addAddressBook", 
vo);
           //Create new published business service messages object for 
           //holding errors and warnings that occur during processing.
           E1MessageList messages = new E1MessageList();
           // Create a new internal value object.
           InternalAddAddressBook internalVO = 
               new InternalAddAddressBook();
           vo.mapFromPublished(context, internalVO);
           //Call business service passing context, connection and 
           //internal VO
           E1MessageList bssvMessages = AddressBookProcessor.addAddressBook
(context, connection, internalVO);
          //Add messages returned from business service to message list
          //for published business service.
           messages.addMessages(bssvMessages);
         //Published Business Service will send either warnings in the
         //Confirm Value Object or throw a published business service 
         //Exception.
           //If messages contains errors, throw the exception
           if (messages.hasErrors()) {
               //Get the string representation of all the messages.
               String error = messages.getMessagesAsString();
               //Throw new BusinessServiceException
               throw new BusinessServiceException(error, context);
           }
           //Exception was not thrown, so create the confirm VO from 
           //internal VO
           ConfirmAddAddressBook confirmVO = 
               new ConfirmAddAddressBook(internalVO);
           confirmVO.setE1MessageList(messages);
           finishPublishedMethod(context, "addAddressBook");
           //return outVO, filled with return values and messages
           return confirmVO;
       } finally {
           //Call close to clean up all remaining connections and 
           //resources.
           close(context, "addAddressBook");
       }
   }

3.5 Handling Errors in the Published Business Service

The published business service class is the JD Edwards EnterpriseOne object that is exposed as a web service. Upon invocation, the published business service returns either a value object that contains data and warning messages, or it throws a BusinessServiceException that contains all errors and warnings that occurred during business processing. The published business service throws BusinessServiceException if any messages of the type error occur in the collection of messages that are returned from the call to the business service method. System errors and database failures are thrown as runtime exceptions. A runtime exception is not handled, but it will cause the published business service to fail and return to the original caller. Throwing an exception causes any database operations that were performed between the default transaction boundaries to roll back, and an error message is sent to the log files.

This code sample shows how to handle errors in the published business service:

                E1MessageList messages = AddressBookProcessor.addAddress
Book(context, connection, internalVO);
           //published business service will send either warnings in the 
             Confirm Value Object or throw a published business service 
             exception.
           //a return status of 2 is an error, throw the exception
           if (messages.hasErrors()) {
               //get the string representation of all the messages
               //RI: Error Handling
               String error = messages.getMessagesAsString(); 
               //Throw new BusinessServiceException(error);
               throw new BusinessServiceException(error, context);
           }
     //exception was not thrown, so create the confirm VO from internal VO
           ConfirmAddAddressBook confirmVO = new ConfirmAddAddressBook
(internalVO);
          confirmVO.setE1MessageList(messages);
          //return confirm VO, filled with return values and messages
           return confirmVO;

3.6 Testing a Published Business Service

You must perform unit testing for the published business service (and business service) that you develop to ensure that the service works as intended. Because published business services depend on the JD Edwards EnterpriseOne system, most of the testing is actually integrated testing. Unit testing should include scenarios that test all decision points in the code. Here are some possible unit tests:

  • Test for each action code that is passed, for example, add, change, cancel.

  • Test 1 line, 5 lines, 0 lines.

  • Perform negative tests.

You can use any of the following methods to test objects in your code:

  • Create a test harness class to test the different functions of the published business service.

    If you create a test harness, you must call business service foundation methods at the start and finish of the test to shut down the process within JDeveloper. You can use the code template E1Test – EnterpriseOne Test Harness Class to generate the framework for your test harness application. You can use this code sample as a model for creating a test harness:

    public static void main(String[] args) throws BusinessServiceException{
          try{  
            //call required prior to starting test from application (main())
            TestBusinessService.startTest();
            //call test method
             testAddNoPhone();
          }
          finally{
            //call required after completing test from application (main())
            TestBusinessService.finishTest();
          }
       }  
    
  • Use the JUnit extension for JDeveloper and create test cases that test the functionality of the published business service.

    JUnit provides a way of running all tests in a suite and can write assertions to determine whether a test passed or failed.

  • Test all functionality through the web service graphical user interface that the embedded OC4J within JDeveloper offers.

    When you use this method, you can save and rerun XML documents.

3.6.1 Testing the Web Service

After unit testing is complete, you create a web service from the public methods in the published business service. You should verify that no problems occur when generating or invoking the web service. Testing the web service is critical because it is possible to pass all tests from a test harness and fail at creating or running a web service.

Use the JDeveloper wizard to test the web service. You access this wizard from JDeveloper New Gallery when you add an object to your project.

3.6.2 WSI Compliance Testing

After the published business service is tested as a web service, you verify that the WSDL is WSI compliant. You use JDeveloper for this task.

See Also:

3.7 Customizing a Published Business Service

The published business services that are delivered with your JD Edwards EnterpriseOne software provide a specific, described unit of work. Although these published business services should cover the functionality that you require, you might need to run additional business logic to meet your specific business requirements. This additional business logic could require processing before, after, or during the delivered published business services unit of work. If you require additional business logic, you should create a custom published business service.

When you customize a published business service, upgrades and updates should be a primary consideration. For example, if your customizations include code changes within the published business service or business service classes that are delivered by JD Edwards EnterpriseOne, then when an upgrade or update is applied to your system, a merge of the code itself would be required. Code merging is extremely difficult to perform and is error prone, and good tooling is hard to find.

To keep updates and upgrades simple, Oracle recommends that you create a new published business service that extends the delivered published business service. You use OMW to create and manage your new, custom published business service. When you extend the delivered published business service, you can add your business logic either before or after the delivered published business service's unit of work. By extending the delivered published business service, your custom classes can access the published business service's functionality, control the transaction scope, and share its context. Extending from a published business service class instead of the internal business service class is significant. Published classes have an explicit contract. When you extend a published class, you can be sure that your customizations will continue to work when your system is updated because the published business service signature and behavior will not change when JD Edwards EnterpriseOne is updated. Internal (business service) classes have no contract and can be changed by JD Edwards EnterpriseOne application development for an update or upgrade.

Extending from published business service classes allows for customizations before and after the delivered published business service's unit of work. If you require custom business logic that processes during the delivered published business service's unit of work, you must create a new published business service and manually copy the delivered published business service and associated business services and modify them as necessary. You use OMW to create and manage your new published business service.

3.7.1 Published Business Service Model

Two methods are required to expose a published business service class as a web service: a public method and a protected method. The sole purpose of the public method is to be called as a web service. The protected method manages and processes the call to the business service classes.

You can use this code sample as a model for your published business service class:

/**
* RI_AddressBookManager is the published business service class exposing 
* functionality within Address Book processes.
*/
public class AddressBookManager extends PublishedBusinessService {
   /**
    * published business service Public Constructor
    */
   public AddressBookManager() {
   }
   /**
    * Published method for Adding an AddressBook Record.
    * Acts as wrapper method, passing null context and null connection,
    * will call protected addAddressBook.
    * @param vo the value object representing input data for Adding an 
    * AddressBook record 
    * @return confirmVO the response data from the business process for adding an 
    * AddressBook record.
    * @throws BusinessServiceException
    */
   public ConfirmAddAddressBook addAddressBook(AddAddressBook vo) throws 
BusinessServiceException {
       return (addAddressBook(null, null, vo));
   }
   /**
    * Protected method for RI_AddressBookManager published business 
    * service.  
    * addAddressBook will make calls to business service classes 
    * for completing business process.
    * @param  vo the value object representing input data for adding an 
    * AddressBook record.
    * @param context conditionally provides the connection for the 
    * database operation and logging information
    * @param connection can either be an explicit connection or null. 
    * If null, the default connection is used.
    * @return response value object is the data returned from the 
    * business process for adding an AddressBook record. 
    * @throws BusinessServiceException
    */
   protected ConfirmAddAddressBook addAddressBook(IContext context, 
                    IConnection connection, 
                    AddAddressBook vo) throws BusinessServiceException {
       //perform all work within try block, finally will clean up any 
       //connections
       try {
           //Call start published method, passing context of null will 
           //return context object so BSFN or DB operation can be called 
           //later.
           //Context will be used to indicate default transaction 
           //boundary, as well as access to formatting and logging 
           //operations.
           context = startPublishedMethod(context, "addAddressBook", vo);
           //Create new published business service messages object for holding
           //errors and warnings that occur during processing.
           E1MessageList messages = new E1MessageList();
           // Create a new internal value object.
           InternalAddAddressBook internalVO = 
               new InternalAddAddressBook();
           vo.mapFromPublished(context, internalVO);
           //Call business service passing context, connection and 
           //internal VO
           E1MessageList bssvMessages = AddressBookProcessor.
addAddressBook(context,connection, internalVO);
           //Add messages returned from business service to message list
          //for published business service.
           messages.addMessages(bssvMessages);
           //A published business service will send either warnings in 
           //the Confirm Value Object or throw a published business 
           //service Exception.
           //If messages contains errors, throw the exception
           if (messages.hasErrors()) {
               //Get the string representation of all the messages.
               String error = messages.getMessagesAsString();
               //Throw new BusinessServiceException
               throw new BusinessServiceException(error, context);
           }
           //Exception was not thrown, so create the confirm VO from 
           internal VO ConfirmAddAddressBook confirmVO = 
               new ConfirmAddAddressBook(internalVO);
           confirmVO.setE1MessageList(messages);
           finishPublishedMethod(context, "addAddressBook");
           //return outVO, filled with return values and messages
           return confirmVO;
       } finally {
           //Call close to clean up all remaining connections and 
           //resources.
           close(context, "addAddressBook");
       }
   }

3.7.2 Extending a Published Business Service

You can add functionality to an existing published business service. Custom processing must take place either before or after the business service call and typically, all processing is within the same transaction boundary. You extend a published business service by doing the following tasks:

  1. Create a new class that extends the original published business service class.

  2. Create a new public method that calls the inherited method for which you are extending functionality.

  3. Create custom processing that takes place either before or after the business service call. Typically, all processing will be within the same transaction boundary.

  /**
  * Published method for Customized Add Address Book 
  * This exposed method will call the method addAddressBook from 
  * parent class.
  * @param vo the value object representing input data for adding 
  * AddressBook record
  * @return confirmVO the response data from the business process for 
  * adding an address book record.
  * @throws BusinessServiceException
  */
       public ConfirmAddAddressBook customAddAddressBook
(AddAddressBook vo) throws BusinessServiceException {
           //perform all work within try block, finally will clean up 
           //any connections
           IContext context = null;
           IConnection connection = null;
           try {
               //Call start published method, passing context of null 
               //will return context object so BSFN or DB operation can
               //be called later.
               //Context will be used to indicate default transaction 
               //boundary, as well as access to formatting and logging 
               //operations.
               context = startPublishedMethod(context, 
"customAddAddressBook",vo);
               //Create new published business service messages object 
               //for holding errors and warnings that occur during 
               //processing.
               E1MessageList messages = new E1MessageList();
               
               //TODO:  This is where a customer customization would be
               //coded.
               //Whatever is coded here is included within the 
               //transaction but occurs prior to calling the published
               //business service.
               
               //Call published business service method
               ConfirmAddAddressBook confirmVO = this.addAddressBook
(context, connection, vo);
              
               //TODO:  This is where a customer customization would be
               //coded.
               //Whatever is coded here is included within the 
               //transaction but occurs after calling the published 
               //business service.
               
               //published business service will send either warnings 
               //in the Confirm Value Object or throw a published 
               //business service Exception.
               //If messages contains errors, throw the exception
               
              if (messages.hasErrors()) {
                   //get the string representation of all the messages
                   String error = messages.getMessagesAsString(); 
                   //Throw new BusinessServiceException
                   throw new BusinessServiceException(error, context);
               }
               
               //Call finish published method, passing the context  
               //to commit default implicit transaction(in case of no 
               //exceptions)
               finishPublishedMethod(context, "customAddAddressBook");
               //return confirmVO, mapped with return values and 
               //messages
               return confirmVO;
           } finally {
               
               //Call close to clean up all remaining connections and 
               //resources.
               close(context,"customAddAddressBook");
           }
          
       }

3.8 Deprecating a Published Business Service

When the signature of a published business service is modified, a new published business service is created to replace the original published business service. The JD Edwards EnterpriseOne deprecation policy for published business services is to ship and support both the original and the replacement published business service for the first release of the replacement published business service. For the second release of the replacement published business service, only the replacement published business service is shipped, but both the original and replacement published business services are supported. For the third release, only the replacement published business service is shipped and supported. The original published business service is no longer supported. For example, oracle.e1.bssv.JP010003 is shipped with 9.0. For 9.1, oracle.e1.bssv.JP010022 is created to replace JP010003. Both published business services are shipped and supported for Release 9.1. For Release 9.2, only the replacement published business service (JP010022) is shipped, but both published business services (JP010022 and JP010003) are supported. For Release 9.3, only JP010022 is shipped and supported. The original published business service (JP010003), which was shipped with 9.0 and 9.1, is no longer supported.