Sunday 2 September 2012

Creating a JD Edwards Business Service (BSSV)

I recently was given a requirement to develop a web service that would simply insert a record into one or more JD Edwards tables. This service required no vaildation, and would simply trust that the input to the web service would be complete and valid.

My knee-jerk reaction was to write a simple BPEL process with a database adapter to the relevant table(s). However, I discovered that JD Edwards actually provides a series of web services out-of-the-box which they refer to as "Business Services" or "BSSVs". A list and description of the standard business services are outlined in the Business Services Reference Guide.

The problem was, there was no BSSV out-of-the-box to insert into the table(s) I required. However, during my investigation of JDE BSSVs, I discovered that it was relatively straight forward to write a custom Business Service, and that the development was even done using java (JDeveloper) and not the JDE tools.

With my interest piqued, I decided to implement the require web service as a JDE BSSV. The tutorial below uses the F0101 as a working example, since the table I actually needed to insert into was a custom one.

Prerequisites

This guide assumes that you have a Windows PC with JDE Tools 9.10 installed, along with JDeveloper 11.1.1.5.0.

Creating the BSSV Object in JDE

Before you can develop the BSSV using JDeveloper, you first need to create the corresponding JDE object within the JDE tools:
  1. Open JD Edwards Solutions Explorer
  2. Type in "OMW" into the Fast Path
  3. Select an OMW Project, and click Add
  4. Under Object Librarian Objects, select the Business Function radio button and click OK
  5. Enter a Name of  JP550100. This name basically indicates that this is a custom BSSV (55) and that it relates to the Address Book (01). This fits in with the recommendation outlined in the Business Services Development Methodology Guide. This guide also recommends to only create one business service for each category, so any future Business Service relating to the Address Book will be developed as additional methods under this same BSSV.
  6. Enter values for the remaining details and click OK:

Configuring and Opening JDeveloper

Now that the BSSV JDE object has been created, you need to tell the JDE tools where your JDeveloper is installed and open your BSSV for implementation:
  1. You should already be in Design for your BSSV, but if not, locate the BSSV object from OMW and click Design
  2. Select the Design Tools tab
  3. Click JDeveloper Install Path button.
  4. Enter the path you chose when installing JDeveloper. For me this was C:\Oracle\Middleware
  5. Click OK
  6. Back on the Design Tools tab, click Invoke JDeveloper
JDeveloper should open and contain your new BSSV project, click OK to "Save Files" if you are prompted. Expand your project, and you should see the basic package structure. 


NOTE: JDeveloper will also display any previous BSSV project that have been opened locally, which for me, includes the standard Address Book Manager BSSV (JP010000).

By opening JDeveloper from JDE, a lot of new features are available including serveral wizards for creating new objects:


These wizards are heavily utilised for the implementation of BSSVs, as well as several other JDE-specific menu items throughout JDeveloper.


Creating Internal Value Objects

Internal Value Objects are objects that can be used as inputs/outputs for business functions or when making database calls. The internal variables of these objects are "JDE  friendly" types like MathNumeric, String and Date, and have names which represent the internal datatype in JDE (e.g. AN8). 

Since we will be calling an insert on the F0101, we will need an Internal Value Object to represent the input to this database call:
  1. Select your BSSV JDeveloper project and select File -> New
  2. On the Current Project Technologies tab select EnterpriseOne -> Classes.
  3. Select Database Value Object and click OK
  4. Click Next  to skip the Welcome screen
  5. Enter the details to search for your table and click Find. I enter F0101 in the Object Name
  6. Select your table and click Next
  7. Select the relevant columns (all in my case) and click Next
  8. Enter InternalAddressBookRecord for the Value Object Name and make sure Internal is selected
  9. Click Finish
A Java class will be created with a private variable for every column in the F0101. The problem is that there is no way to access these variables: we need getters and setters. Luckily, JDeveloper can generate these for us by right clicking the java source and selecting Generate Accessors. Simply select all of the available fields, and click OK.

Creating Published Value Objects

Published Value Objects are used as the input and outputs to the Business Service, which are available to external systems. The internal variables of these objects are "XML/Web Service friendly" types like Integer, BigDecimal, String and Calendar, and have user friendly names like addressBookNumber (instead of AN8).

We want to create an input variable to this BSSV with all of the fields of the Address Book Master, but this time, in XML and user friendly format:
  1. Select your BSSV JDeveloper project and select File -> New
  2. On the Current Project Technologies tab select EnterpriseOne -> Classes.
  3. Select Database Value Object and click OK
  4. Click Next  to skip the Welcome screen
  5. Enter the details to search for your table and click Find. I enter F0101 in the Object Name
  6. Select your table and click Next
  7. Select the relevant columns (all in my case) and click Next
  8. Enter AddressBookRecord for the Value Object Name and make sure Published is selected
  9. Click Finish
  10. Generate Accessors the same way you did previously
Since I do not require any specific output from my BSSV, I am not creating a Value Object for it. Instead, I will simply use the MessageValueObject as the return type. Normally your return type will extend this class, but there is nothing stopping you from using the base class itself.

Creating the Published Business Service Class

With our value objects sorted, we can now create the actual BSSV implementation:
  1. Select your BSSV JDeveloper project and select File -> New
  2. Click Classes under the  EnterpriseOne category
  3. Select Published Business Service Class and click OK
  4. Enter the following details:
    • Name - CustomAddressBookManager
    • Method Name - insert
    • Input Class - oracle.e1.bssv.JP550100.valueobject.F0101
    • Return Class - oracle.e1.bssvfoundation.base.MessageValueObject
  5. Click OK
The Java class for the implementation of you BSSV is now created. You will notice that there are a few errors and "TODO" references that will be address by your implementation.

Transforming Between Published and Internal Value Objects

Looking at the method that was generated for our Business Service, you can see that the input is of the Published Value Object type F0101. When we call the insert into the Address Book Master table, we will need an object of the Internal Value Object type InternalF0101, meaning we will need to write code which converts from the Published object to the Internal version.

I have chosen to do implement this as a new constructor for the Internal class which accepts the Published type as an input parameter.
public InternalF0101 (F0101 vo) {
    this.F0101_AN8 = new MathNumeric(vo.getAddressNumber());
    this.F0101_ALKY = vo.getAlternateAddressKey();
    this.F0101_EFTB = vo.getDateBeginningEffective().getTime();
    ...
}
The code above needs to set every internal variable of InternalF0101 to the corresponding variable within the F0101 input object. 

NOTE: The javadoc in the Published Object contains an EnterpriseOne Alias above every internal variable declaration which can be used to help when mapping to/from the Internal Object internal variables e.g. addressBookNumber -> F0101_AN8.

Implementing the BSSV

Within the BSSV class, there are three "TODO" statements to guide you in your implementation:
//TODO: Create a new internal value object.
//TODO: Call BusinessService passing context, connection and internal VO
//TODO: Add messages returned from BusinessService to message list for PublishedBusinessService.
Under the first TODO, we want to construct the Internal Value Object to be used when inserting into the table. We can use the new constructor we created above, passing in the Published Value Object:
// Create a new internal value object.
InternalF0101 internalVO = new InternalF0101(vo);
The second TODO requires us to use a new context menu item in JDeveloper added by JDE:
  1. Right-click the BSSV source file under the second TODO
  2. Select Create Database Call
  3. Click Next on the Welcome screen
  4. Select Insert and click Next
  5. Search for and select your table (F0101), then click Next
  6. Select the relevant columns (all in my case) and click Next
  7. Review the generated database operation and click Finish
This wizard will create a new private method that performs the database insert as well as add the call to this method to wherever you initiated the wizard (for us, under the second TODO):
// Call BusinessService passing context, connection and internal VO
insertToF0101(context, connection, internalVO);
The generated private method will have many errors because the wizard defaults the input value object to be of the type InputVOType. We need to change this to our Internal object type (bold below):
private static E1MessageList insertToF0101(IContext context, IConnection connection, InternalF0101 internalVO) {
To address the final TODO we need to use the return value from the private method which performs the database insert. Modify the line under the second TODO to use the capture the return value:
// Call BusinessService passing context, connection and internal VO
messages = insertToF0101(context, connection, internalVO);
At this point, there should only be one error left in the implementation, which occurs on the following line:
MessageValueObject confirmVO = new MessageValueObject(internalVO);
Simply remove the highlighted text above, and your BSSV implementation is now complete.

Testing the BSSV Logic

To test the code that you have written, you can run the BSSV class locally with a main method like that below:
public static void main(String args[]) {
    CustomAddressBookManager a = new CustomAddressBookManager();
    F0101 f = new F0101();
    f.setAddressNumber(new Integer(123));
    f.setAlternateAddressKey("abc");
    f.setDateBeginningEffective(Calendar.getInstance());
    // TODO set other fields
 
    try {
        a.insert(f);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Running this method will insert the relevant record into the database with the correct values. The values in the table will be in the correct JDE format for dates, numbers etc.

Running the exact same code again, correctly results in the following error:
oracle.e1.bssvfoundation.exception.BusinessServiceException:
Description: Table/View - Error during database operation: [DUPLICATE_KEY_ERROR] Duplicate key error obtained for table F0101.,
Resolution: See logs for detail of database operation failure

9 comments:

  1. Finally the Jdeveloper must be closed and we need to do the check-in business function in JD tools?

    ReplyDelete
    Replies
    1. You can check in your business function using JDE tools when development is complete. It is not necessary to close JDeveloper before checking in.

      Delete
  2. I have some problem. When I try check-in my business function, on the list of artifacts I have *.jpr file which can not be checked in. Do you have idea, what is wrong?

    ReplyDelete
    Replies
    1. The .jpr file is the JDeveloper project file, which is created by JDE tools when you click "Invoke JDeveloper" for a BSSV objects.
      This file does not get checked in. Only the .java files need to be checked in.

      Delete
  3. Sedulous Technologies provides support for your #JD #Edwards system, enabling you to save up to 90 percent on your total maintenance costs while avoiding expensive forced upgrades. are you looking JD Edwards Service Provider
    JD Edwards Service Provider

    ReplyDelete
  4. Hey thanks for this, just had to update one of these myself, something that's been running for seven years! This helped me out...

    ReplyDelete
  5. This is valid for 2020 JDE E1 9.1?

    ReplyDelete