Skip to content
May 24, 2012 / danilo

How to create a View Object based on a WebService

Today we are explaining how to create a View Object based on a Web Service.

For this example we have a legacy database function that returns a list of items in xml format, instead of developing a new query we can reuse this with some tricks.

The first step is to publish the database package as a Web Service, this can be done in JDeveloper using the DatabaseNavigator view. In this case we have a separate application only for publishing database packages as Web Services, and then we deploy it to our application server.

 

To check if everything is working log into the Enterprise Manager and verify if the URL for the deployed web service is working.

If everything is ok then in your project create a Web Service Proxy ,


Insert the WSDL URL of the service (the URL is on the Enterprise Manager) and go on until the proxy is created. Now you should have these generated files in your project directory


Now to use the Web Service we must create a Java class to work as a client for the service interface. This class extends ViewObjectImpl that will be used when the View Object is created. In this example our Web Service returns a String with xml format, this String is processed and a list of items is returned to be populated in the View Object.


public class ProxyListItemsWS extends ViewObjectImpl {

    @WebServiceRef
    private static PkgPecasService_Service itemsService;

private long rows = -1;

public ProxyListItemsWS() {
      super();
}

public long getAllRows() {
      return this.rows;
}

public List<Item> getItems(int pageNumber, int pageSize, String id, String description,
                String articleId) {

       String xml = "";
       this.rows = -1;
       itemsService = new PkgPecasService_Service();
       PkgPecasService port = itemsService.getPkgPecasServicePort();
       BigDecimal page = BigDecimal.valueOf(pageNumber);
       BigDecimal pageSz = BigDecimal.valueOf(pageSize);

       String ub = "";
       String pRep = "";
       String pDescRep = "";
       String strRep = "";
       String li = "";
       xml = port.listxml(page, pageSz, ub, id, articleId, description, li, pRep, pDescRep, "pt-PT", "pt-PT", "ADMIN", "0418",

       if (xml == null || xml.trim().isEmpty())
           return new LinkedList<Item>();

       return parseListItemsXML(xml);
   }

....

The important in the above example is the the endpoint interface itemsService = new PkgPecasService_Service(); and the service port to invoke the method PkgPecasService port = itemsService.getPkgPecasServicePort(); .

We now have everything to create the View Object (rows populated programmatically) based on a Web Service, and generate its Java class.

 

The View Object class now extends from the client class we created and now can invoke the Web Service and populate the rows. The View Object methods are overridden to perform our logic as it shows on the following code snippet.


package model;

import java.sql.ResultSet;

import java.util.List;

import oracle.jbo.server.ViewObjectImpl;
import oracle.jbo.server.ViewRowImpl;
import oracle.jbo.server.ViewRowSetImpl;

import proxy.Item;
import proxy.ProxyListItemsWS;

public class ListItemsVOImpl extends ProxyListItemsWS {

  private boolean initialized = false;
  private List<Item> rowData = null;
  private boolean isQueriable = false;
  long rows = -1;
  int ROWS_PER_PAGE = 10;

  private String id;
  private String description;
  private String articleId;
  private int previousPage = -1;

  public ListItemsVOImpl() {
    this.id = "";
    this.description = "";
    this.articleId = "";
  }

  protected void executeQueryForCollection(Object qc, Object[] params,
int noUserParams) {

    if (!isQueriable)
      return;

    if (!initialized) {
      initialize();
      initialized = true;
      if (this.getAllRows() <= 0)
        return;
    }

    // Initialize our fetch position for the query collection
    setFetchPos(qc, 0);
    super.executeQueryForCollection(qc, params, noUserParams);
  }

  protected boolean hasNextForCollection(Object qc) {
    return getFetchPos(qc) < rows;
  }

  protected ViewRowImpl createRowFromResultSet(Object qc,
ResultSet resultSet) {
    if (!isQueriable)
      return null;

    ViewRowImpl r = createNewRowForCollection(qc);
    int pos = getFetchPos(qc);

    long totalLoadedPages = (long)Math.ceil((double)rowData.size() / (double)ROWS_PER_PAGE);
    long loadedPageFactor = totalLoadedPages * ROWS_PER_PAGE;

    if (pos == loadedPageFactor) {
      initVO((int)totalLoadedPages);
    }

    if (pos == -1) {
      pos = 0;
    }

    populateAttributeForRow(r, 0, rowData.get(pos).getId());
    populateAttributeForRow(r, 1, rowData.get(pos).getDescription());
    populateAttributeForRow(r, 2, rowData.get(pos).getStock());
    populateAttributeForRow(r, 3, rowData.get(pos).getArticleId());
    populateAttributeForRow(r, 4, rowData.get(pos).getPvp());
    populateAttributeForRow(r, 5, rowData.get(pos).getNome());
    setFetchPos(qc, pos + 1);

    return r;
  }

  public long getQueryHitCount(ViewRowSetImpl viewRowSet) {
    if (!isQueriable)
      return -1;

    return rows;
  }

  private void initialize() {
    initVO(0);

    if (rowData != null) {
      rows = this.getAllRows();
    } else {
      rows = 0;
    }
  }

  public void setAttributes(String id, String description, String articleId) {

    if (id != null)
      this.id= id;
    if (description != null)
      this.description = description;
    if (articleId != null)
      this.articleId = articleId;
 }

  public void setIsQueriable(boolean bool) {
    this.isQueriable = bool;
  }

  public void setInitialize(boolean bool) {
    this.initialized = bool;
    this.clearCache();
    this.rowData = null; //new
  }

  private void initVO(int page) {
    List<Item> rowDataCollection =
    this.getItems(page, ROWS_PER_PAGE, this.id, this.description, this.articleId);

    if (rowData == null) {
      rowData = rowDataCollection;
    } else {
      for (int i = 0; i < rowDataCollection.size(); i++) {
        rowData.add(rowDataCollection.get(i));
      }
    }
  }

  private void setFetchPos(Object rowset, int pos) {
    if (pos == rows) {
      setFetchCompleteForCollection(rowset, true);
    }

    setUserDataForCollection(rowset, new Integer(pos));
  }

  private int getFetchPos(Object rowset) {
    int value = ((Integer)getUserDataForCollection(rowset)).intValue();
    return value;
  }

}

Now we can create a page and show a table, bind to the View Object, with the results. Additionally, we also created a managed bean to obtain the values from the input text and to invoke the View Object execute query method.



public String executeSearch() {

    //obtain app module instance to retrieve view object
    AppModuleImpl appModule = (AppModuleImpl)BindingContext.getCurrent().findDataControl("AppModuleDataControl").
          getApplicationModule();

    ListItemsVOImpl viewObject = appModule.getListItemsVO1();
    viewObject.setIsQueriable(true);
    viewObject.setInitialize(false);

    String id = this.id.getValue() != null ? this.id.getValue().toString() : null;
    String description = this.getDescription().getValue() != null ?
            this.getDescription().getValue().toString() : null;
    String articleId = this.articleId.getValue() != null ?
            this.articleId.getValue().toString() : null;

    viewObject.setAttributes(id, description, articleId);
    viewObject.executeQuery();

    return null;
  }

....


This is our View Object displayed as a read only table, the result of the search comes in xml format that is processed to a list of items and that list is used to populate the rows, and now we have a View Object that is based on a Web Service.

 

4 Comments

Leave a Comment
  1. Don / Jun 24 2014 5:04 am

    What version of jdeveloper is this on? It’s not working for me on 11.1.1.4. It fails with ORA-00936: missing expression. It seems to be trying to execute sql that doesn’t exist.

    • danilo / Aug 18 2014 9:37 am

      Hi, it is in version 11.1.1.6.

  2. Apoorv / Jul 2 2014 1:14 pm

    Hi can you please share parseListItemsXML Method for help in parsing,

    Thanks & Regards
    Apoorv Jain

  3. Tony / Oct 2 2014 11:06 am

    Hi there,

    Would you be able to show us how to do this with a REST web service?

Leave a reply to danilo Cancel reply