12 Feb 2011

ADF BC. Working with Oracle collection data types

Introduction
ADF BC allows us to use Oracle object types in quite easy way. If your table contains attribute of Oracle object type, JDeveloper creates corresponding domain class automatically. Or you can create it manually using Create Domain Wizard. After that you can work with the attribute as if it had regular type. But!  If you need to work with collection type (like ".. as table of ..."), it works in a little bit different way.


Let's do it
I've got in my database the following sql type definition:
create or replace type varchar2_array_type as table of varchar2(200)

And the following table:
create table testarray (
 SomeField Number,
 ArrValue VARCHAR2_ARRAY_TYPE)

nested table ArrValue store as arrvalue_tab return as value;

In JDeveloper I created entity object on this table and payed some attention to the definition of ArrValue attribute.  In JDev 11.1.1.2.0 you will get this:


Have a look at the type of ArrValue attribute. It is String!!! I don't know why.
In JDev 11.1.1.4.0 you will get this:



JDev 11.1.1.4.0 seems to be a bit smarter as for working with collection types. But never mind if you're using JDev 11.1.1.2.0 or earlier.  Magic button "Browse" will help. You can manually choose needed type - oracle.jbo.domain.Array.


It works. Trust me.
After creating default view object and dropping it from the data control palette to page as an ADF Form, you will get this:

The default DomainArrayConverter represents our array as a comma separated string. If you don't like the default behavior, it is possible to show array values in a table. Have a look at the following jspx source code:


   
      
   


And you will get this:


You can also implement your custom JSF converter for Array type. For example the following converter represents  Array as multi-row string:

public class StringArrayConverter implements Converter{
 public StringArrayConverter() {
     super();
 }
    
 private Array getArray(String value) {
     String[] splittArray = value.split("\n");
     Array arr = new Array(splittArray);
     return arr;
 }

 public Object getAsObject(FacesContext context, UIComponent component,
                           String newValue) throws ConverterException {
    if ((newValue == null) || "".equals(newValue))
         return null;
     return getArray(newValue);
  }


 public String getAsString(FacesContext context, UIComponent component,
                           Object value) throws ConverterException {
     if (value == null)  return null;
 
     Array array = (Array)value;
     if (array.getSize() <= 0) return null;
     Object[] data = array.getArray();        
     StringBuffer result = new StringBuffer();
        if (data.length > 0) {
            result.append(data[0]);
            for (int i=1; i < data.length; i++) {
                result.append("\n");
                result.append(data[i]);
            }
        }
    return result.toString();
 }
Create inputText using this converter

And you will get this:
For sure using oracle.jbo.domain.Array is not limited by arrays of varchar2 or number. It allows us to work with really complex data type structures.

4 comments:

  1. Hi Eugene,
    My name is Luis.

    I'm new Jdeveloper and I have this Issue on Jdev 11gR2. I have an af:table using a Input Text with Lovs, the issue happend when I select from the list of value and press the TAB key, all next required items show the error (value must be entered). this only happend on af:table and with InputList of value or combobox with lovs. thank you
    luisviloriat@hotmail.com

    ReplyDelete
  2. Hi Luis!
    You can avoid unnecessary validation by adding valueChangeListener for your InputListofValue (or inputComboboxListOfValues) with the following code:

    public void valueChangeEvent(ValueChangeEvent valueChangeEvent) {
    UIComponent c = valueChangeEvent.getComponent();
    ((UIXValue) c).setValue(valueChangeEvent.getNewValue());
    FacesContext.getCurrentInstance().renderResponse();
    }

    ReplyDelete
  3. Aino Andriessen7 April 2014 at 03:29

    Hi Eugene,

    Great post.
    I'm trying to implement the 'table' way and it works very well to display the data.
    However, it seems that we're not able to update the data. The new values just seam to disappear.
    Any suggestion; we're using 11.1.1.7?

    Regards
    Aino

    ReplyDelete
    Replies
    1. Hi Aino,
      Thanks for the question. Yes, the array returned by oracle.jbo.domain.Array.getArray() is immutable one and it can't be modified directly.
      You gotta do the following:
      1. Make a copy of the bindings.Arrvalue.inputValue.array
      2. Set this copy as table's value
      3. At the Update Model Values phase wrap the copy back into oracle.jbo.domain.Array and put it to the Arrvalue.inputValue.

      You can download a sample application for JDev 11.1.1.7 here
      sample application


      Thanks,
      Eugene

      Delete

Post Comment